同步和非同步例子(linux)
阿新 • • 發佈:2019-02-13
《POSIX多執行緒程式設計》——David R.Buten
同步
alarm.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int seconds;
char line[128];
char message[64];
while (1) {
printf("Alarm> ");
if (NULL == fgets(line, sizeof(line), stdin)) exit(0);
if (1 >= strlen(line)) continue;
if (2 > sscanf(line, "%d %64[^\n]", &seconds, message))
fprintf(stderr, "Bad command\n");
else {
sleep(seconds);
printf("(%d) %s\n", seconds, message);
}
}
return 0;
}
gcc -o alarm alarm.c
侷限性:一次只能處理一個鬧鐘請求。
非同步(多程序)
alarm_fork.c
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>
#define errno_abort(text) do { \
fprintf (stderr, "%s at \"%s\":%d: %s\n", \
text, __FILE__, __LINE__, strerror(errno)); \
abort(); \
} while (0)
int main(int argc, char *argv[]) {
int status;
char line[128];
int seconds;
pid_t pid;
char message[64];
while (1) {
printf("Alarm> ");
if (NULL == fgets(line, sizeof(line), stdin)) exit(0);
if (1 >= strlen(line)) continue;
if (2 > sscanf(line, "%d %64[^\n]", &seconds, message))
fprintf(stderr, "Bad command\n");
else {
pid = fork();
if ((pid_t)-1 == pid) // failure
errno_abort("Fork");
if ((pid_t)0 == pid) { // child
sleep(seconds);
printf("(%d) %s\n", seconds, message);
exit(0);
}
else { // parent
do {
pid = waitpid((pid_t)-1, NULL, WNOHANG); // 非阻塞等待子程序結束,回收子程序
//printf("#%d\n", pid);
if ((pid_t)-1 == pid)
errno_abort("Wait for child");
} while ((pid_t)0 != pid);
}
}
}
return 0;
}
gcc -o alarm_fork alarm_fork.c
alarm_fork.c中的main函式沒有直接呼叫sleep函式 ,而是建立了一個子程序,在子程序中非同步地呼叫sleep函式和printf,而父程序則繼續執行。
呼叫waitpid函式回收子程序,並設定WNOHANG(父程序不必掛起等待子程序的結束)。
非同步(多執行緒)
alarm_thread.c
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define err_abort(code, text) do { \
fprintf(stderr, "%s at \"%s\":%d: %s\n", \
text, __FILE__, __LINE__, strerror(errno)); \
abort(); \
} while (0)
#define errno_abort(text) do { \
fprintf(stderr, "%s at \"%s\":%d: %s\n", \
text, __FILE__, __LINE__, strerror(errno)); \
abort(); \
} while (0)
typedef struct alarm_tag {
int seconds;
char message[64];
} alarm_t;
void* alarm_thread(void *arg) {
alarm_t *alarm = (alarm_t *)arg;
int status;
status = pthread_detach(pthread_self()); // 分離自己,在它終止後立刻回收
if (0 != status)
err_abort(status, "Detach thread");
sleep(alarm->seconds);
printf("(%d) %s\n", alarm->seconds, alarm->message);
free(alarm);
return NULL;
}
int main(int argc, char *argv[]) {
int status;
char line[128];
alarm_t *alarm;
pthread_t thread;
while (1) {
printf("Alarm> ");
if (NULL == fgets(line, sizeof(line), stdin)) exit(0);
if (1 >= strlen(line)) continue;
alarm = (alarm_t *)malloc(sizeof(alarm_t));
if (NULL == alarm)
errno_abort("Allocate alarm");
if (2 > sscanf(line, "%d %64[^\n]", &alarm->seconds, alarm->message)) {
fprintf(stderr, "Bad command\n");
free(alarm);
}
else {
status = pthread_create(&thread, NULL, alarm_thread, alarm);
if (0 != status)
err_abort(status, "Create alarm thread");
}
}
return 0;
}
gcc -o alarm_thread alarm_thread.c -lpthread