如题所述:
编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
-----------------------------------------------------------------------------------------------------------------
用pthread_cond_signal,理论上会引起本该得到信号的线程一直处于饥饿状态,但我试过了,每次运行都ok。如果尝试线程数量多一点会怎么样,like 100个。没试过。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <errno.h> pthread_cond_t cond_a; pthread_mutex_t mylock; int g_flag; #define NUM 3 void * func(void *arg) { int i; int name = (int)arg; printf("my name [%d]\n", name); for(i = 0; i<10;i++) { if( pthread_mutex_lock(&mylock)) { printf("pthread_mutex_lock error errmsg[%s]\n", strerror(errno)); exit(0); } while(1) { if(g_flag == name) { g_flag = (g_flag+1)%NUM; printf("%c ", 'A' + name); break; } else { if(pthread_cond_wait(&cond_a, &mylock)) { printf("wait error errmsg[%s]\n", strerror(errno)); exit(0); } } } if(pthread_mutex_unlock(&mylock)) { printf("pthread_mutex_unlock error errmsg[%s]\n", strerror(errno)); exit(0); } //if(pthread_cond_broadcast(&cond_a)) if(pthread_cond_signal(&cond_a)) { printf("pthread_cond_broadcast error errmsg[%s]\n", strerror(errno)); exit(0); } } printf("\n"); pthread_exit(NULL); } int appInit() { g_flag = 0; pthread_mutex_init(&mylock, NULL); pthread_cond_init(&cond_a, NULL); return 0; } int appDone() { pthread_cond_destroy(&cond_a); pthread_mutex_destroy(&mylock); return 0; } int main(int argc, char *argv[]) { pthread_t th[NUM]; int ret; int i; ret = appInit(); if(ret) { printf("appinit failure\n"); return -1; } for( i = 0; i < NUM; i++) { ret = pthread_create(&th[i], NULL, func, (void*)i); if(ret) { printf("pthread_create ta error [%s]\n", strerror(errno)); return 1; } } for( i = 0; i < NUM; i++) pthread_join(th[i], NULL); printf("main thread exit\n"); ret = appDone(); if(ret) { printf("appDone failure\n"); return -1; } return 0; }
这个版本的代码好搞,--!!
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <errno.h> #include <stdarg.h> #include <unistd.h> #include <limits.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/types.h> #include <sys/time.h> #include <signal.h> #define myprintf( ... ) \ do{ \ mprintf(__FILE__, __FUNCTION__, __LINE__,##__VA_ARGS__); \ }while(0) int mprintf(const char *file_name, const char *func_name, int line, const char *fmt, ...) { va_list strArgPtr; int la,lb; la = fprintf(stdout, "[%-15s]-[%-10s]-[%04d]", file_name, func_name, line); va_start(strArgPtr, fmt); lb = vfprintf(stdout, fmt, strArgPtr); va_end(strArgPtr); printf("\n"); fflush(stdout); return (la+lb); } void funb(int arg) { myprintf("B"); } void func(int arg) { myprintf("C"); } int main(int argc, char *argv[]) { int ret; int i; sigset(SIGALRM, funb); sigset(SIGUSR1, func); for ( i = 0; i < 10; i++) { myprintf("A"); kill(getpid(), SIGALRM); kill(getpid(), SIGUSR1); } myprintf("main thread exit\n"); return 0; }
这个版本更搞笑,不过有一些条件,不然运行一行就退出
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <errno.h> #include <stdarg.h> #include <unistd.h> #include <limits.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/types.h> #include <sys/time.h> #include <signal.h> #define NUM 3 #define myprintf( ... ) \ do{ \ mprintf(__FILE__, __FUNCTION__, __LINE__,##__VA_ARGS__); \ }while(0) int shutdown; pthread_mutex_t lock; int mprintf(const char *file_name, const char *func_name, int line, const char *fmt, ...) { va_list strArgPtr; int la,lb; la = fprintf(stdout, "[%-15s]-[%-10s]-[%04d]", file_name, func_name, line); va_start(strArgPtr, fmt); lb = vfprintf(stdout, fmt, strArgPtr); va_end(strArgPtr); printf("\n"); fflush(stdout); return (la+lb); } void funa(int arg) { myprintf("A"); } void funb(int arg) { myprintf("B"); } void func(int arg) { myprintf("C"); } void *fun(void * arg) { int name = (int)arg; sigset_t set; switch(name) { case 0: sigset(SIGALRM, funa); sigfillset(&set); sigdelset(&set, SIGALRM); pthread_sigmask(SIG_SETMASK, &set, NULL); break; case 1: sigset(SIGUSR1, funb); sigfillset(&set); sigdelset(&set, SIGUSR1); pthread_sigmask(SIG_SETMASK, &set, NULL); break; case 2: sigset(SIGUSR2, func); sigfillset(&set); sigdelset(&set, SIGUSR2); pthread_sigmask(SIG_SETMASK, &set, NULL); break; default: myprintf("u tm dou wo!"); return 0; } for(;;) { pause(); pthread_mutex_lock(&lock); if(shutdown) { pthread_mutex_unlock(&lock); pthread_exit(NULL); } pthread_mutex_unlock(&lock); } } int main(int argc, char *argv[]) { int ret; pthread_t th[NUM]; pthread_mutex_init(&lock, NULL); int i; shutdown = 0; for(i = 0; i< NUM; i++) { ret = pthread_create(&th[i], NULL, fun, (void *)i); if ( ret ) { myprintf("create failure %d", i); exit(0); } } sleep(1); for ( i = 0; i < 10; i++) { pthread_kill(th[0], SIGALRM); pthread_kill(th[1], SIGUSR1); pthread_kill(th[2], SIGUSR2); sleep(1); } pthread_mutex_lock(&lock); shutdown = 1; pthread_mutex_unlock(&lock); pthread_kill(th[0], SIGALRM); pthread_kill(th[1], SIGUSR1); pthread_kill(th[2], SIGUSR2); for(i = 0; i< NUM; i++) { pthread_join(th[i], NULL); } pthread_mutex_destroy(&lock); myprintf("main thread exit\n"); return 0; }
综上所述,第一个版本最牛,不需要额外条件,并且完全满足题意,是三个线程,而不是仅仅满足输出。第三个版本需要的运行条件最多,比如第一个sleep不能没有,要不然线程们的信号还没安装,主线程早早发出信号,结果查无此信号,直接game over。第二个sleep照样不能缺失,有个不太确认的答案,线程在第一次响应信号的过程中调用了IO,导致优先级降低,主线程此时发出信号,还是查无此人,直接game over。
浙公网安备 33010602011771号