编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推

来源:互联网 发布:金山软件管家office 编辑:程序博客网 时间:2024/03/29 08:54

  编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。       

        好长时间没有再想写代码了,虽然自己还没有毕业,处于学习的阶段,但是很少是主动的写过多少,代码量太少是一大障碍。在不久就面临毕业找工作,刚才看了许久的各大公司的笔试题,看懂的没有几道,会的更少。自己弱爆了,怎么办。在这里,我把自己会的尽量写,借此激励自己。 

      老师讲的这是迅雷的笔试题: 是不是无关紧要,主要是上次考试的时候这就是最后一道题,要求用手写确实不容易.

     题意很明了,要求也很简单,自己傻逼一样一看就笑了,用一个sleep()愉快的完成了这道题,感觉还很牛B..下面是当时自己在试卷上的作答:

[c] view plaincopy
  1.    
  2. #include<stdio.h>  
  3. #include<stdlib.h>  
  4. #include<string.h>  
  5. #include<errno.h>  
  6. #include<pthread.h>  
  7. #include<unistd.h>  
  8.   
  9. void *th_fun(void* arg){  
  10.      int i=0;  
  11. while(i < 10){  
  12.     printf("the num is:%lx\n",pthread_self());  
  13.     i++;  
  14.     usleep(150);  
  15. }  
  16.     return ((void *)0);  
  17. }  
  18. int main(void){  
  19.     pthread_t th1,th2,th3;  
  20.     //参数的类型: int*  
  21.     if(0 != pthread_create(&th1,NULL,th_fun,NULL)){  
  22.         fprintf(stderr,"pthread %s\n",strerror(errno));  
  23.         exit(1);  
  24.     }  
  25.   
  26.     usleep(50);  
  27.     if(0 != pthread_create(&th2,NULL,th_fun,NULL)){  
  28.         fprintf(stderr,"pthread %s\n",strerror(errno));  
  29.         exit(1);  
  30.     }  
  31.     usleep(50);  
  32.     if(0 != pthread_create(&th3,NULL,th_fun,NULL)){  
  33.         fprintf(stderr,"pthread %s\n",strerror(errno));  
  34.         exit(1);  
  35.     }  
  36.     pthread_join(th1,NULL);  
  37.     pthread_join(th2,NULL);  
  38.     pthread_join(th3,NULL);  
  39. return 0;  
  40. }  
  41. </unistd></pthread></errno></string></stdlib></stdio>  
结果是把每个线程的编号打印三遍,但是用sleep确实没有什么意思,所以这么做只能得0分。创建线程的时候用了usleep(50)不然打印出结果就是错的,sleep本身就不精确。没多少线程控制的含量,没有用到互斥锁和条件变量。

假设有三个线程A, B, C;A线程首先执行,B线程等待A结束后执行,C线程等待B结束后执行,A线程又要等待C线程结束后执行,B再等待A,C再等待B....以此类推,是一个循环等待的过程,每一个线程要做的事情:1.抢到锁,设置标志位为1(告诉上家自己在等待信号);2.收到上家的信号,立即设置标志为为0,并打印出自己的线程号;3.确定下家是否在等待,确定下家在等待后,立即发送信号给下家,再打开锁,usleep(20)(让其他线程抢到锁)。

其中有两个要注意的地方:1.三个线程创建好后,三个线程都在死等待 [A等C,B等A,C等B] 所以首先手动代替C为A发送信号,让程序执行。2.A线程的10次循环结束后,flag标志位是0,而此时C线程还没有执行完毕,C要检查A的标志为是否为1再给A发送信号,所以在A循环结束后把它的flag标志为置为1。

看程序:

[c] view plaincopy
  1.    
  2. #include<stdio.h>  
  3. #include<errno.h>  
  4. #include<string.h>  
  5. #include<stdlib.h>  
  6. #include<pthread.h>  
  7.   
  8. #define PRINTTIME 10  
  9. /*互斥锁 MUTEX*/  
  10. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  
  11. /*条件变量*/  
  12. pthread_cond_t condA_B = PTHREAD_COND_INITIALIZER;  
  13. pthread_cond_t condB_C = PTHREAD_COND_INITIALIZER;  
  14. pthread_cond_t condC_A = PTHREAD_COND_INITIALIZER;  
  15.   
  16. int flagA = 0,flagB = 0,flagC = 0;  
  17.   
  18. void *th_A_C(void *arg){  
  19.   
  20.     printf("A come!\n");  
  21.     int i = 0;  
  22.     char *name = (char *)arg;  
  23.     while(i < PRINTTIME){  
  24.         pthread_mutex_lock(&mutex);  
  25.         //printf("A LOCKED\n");  
  26.   
  27.         flagA = 1;  
  28.         /*等待C的信号*/  
  29.         pthread_cond_wait(&condC_A,&mutex);  
  30.         flagA = 0;  
  31.         printf("%c:%d-->%lx\n",*name,i,pthread_self());  
  32.         /*发信号给B*/  
  33.         /*在发信号给B之前,先检测B有没有在等待*/  
  34.         /*若B在等待,在这里就可以检测到标志位flagB == 1*/  
  35.         while(!flagB){  
  36.   
  37.             pthread_mutex_unlock(&mutex);  
  38.             usleep(30);  
  39.             //          printf("--------------------------wait flagB\n");  
  40.             pthread_mutex_lock(&mutex);  
  41.   
  42.         }/*循环结束表示flagBC为1,就是B已经加锁,并在等待A给它信号,所以现在A发信号给B*/  
  43.   
  44.         //      printf("signal A--->B finished!\n");  
  45.         pthread_cond_signal(&condA_B);        
  46.         pthread_mutex_unlock(&mutex);  
  47.         //      printf("%c UNLOCK!\n",*name);  
  48.         i++;  
  49.         usleep(20);  
  50.     }  
  51.     /*A的循环结束的时候把自己的flagA 位置为1,欺骗C线程 让C线程以为A这边准备好了,然后发信号给他。这样可以避免C判断A没有再等带它的标志一直死循环状态退不出来*/  
  52.     flagA = 1;  
  53. }  
  54.   
  55.   
  56.   
  57. void *th_B_A(void *arg){  
  58.   
  59.     printf("B come!\n");  
  60.     int i = 0;  
  61.     char *name = (char *)arg;  
  62.     while(i < PRINTTIME){  
  63.   
  64.         pthread_mutex_lock(&mutex);  
  65.         //      printf("B LOCKED\n");  
  66.         /*B抢到锁,设置标志位flagBC = 1*/  
  67.         flagB = 1;  
  68.         /*等待A的信号*/  
  69.         pthread_cond_wait(&condA_B,&mutex);  
  70.         flagB = 0;  
  71.         printf("%c:%d-->%lx\n",*name,i,pthread_self());  
  72.         /*发信号给C*/  
  73.         /*在发信号给C之前先检测C有没有在等待*/  
  74.         /*若C在等待则flagC == 1*/  
  75.         while(!flagC){  
  76.   
  77.             pthread_mutex_unlock(&mutex);  
  78.             usleep(30);  
  79.             //          printf("--------------------------wait flagC\n");  
  80.             pthread_mutex_lock(&mutex);  
  81.         }  
  82.   
  83.         /*循环结束表示flagC 已经为1 ,所以开始给C发信号*/  
  84.         //      printf("signal B--->C finished!\n");  
  85.         pthread_cond_signal(&condB_C);        
  86.         pthread_mutex_unlock(&mutex);  
  87.         //      printf("%c UNLOCK!\n",*name);  
  88.   
  89.         i++;  
  90.         usleep(20);  
  91.     }  
  92. }  
  93.   
  94.   
  95.   
  96. void *th_C_B(void *arg){  
  97.   
  98.     printf("C come!\n");  
  99.     int i = 0;  
  100.     char *name = (char *)arg;  
  101.     while(i < PRINTTIME){  
  102.   
  103.         pthread_mutex_lock(&mutex);  
  104.         //      printf("C LOCKED\n");  
  105.         flagC = 1;  
  106.         /*等待B的信号*/  
  107.         pthread_cond_wait(&condB_C,&mutex);  
  108.         flagC = 0;  
  109.         printf("%c:%d-->%lx\n",*name,i,pthread_self());  
  110.         /*发信号给A*/  
  111.         /*发信号给A 之前先检测A有没有在等待,若在等待 则flagA == 1*/  
  112.   
  113.         while(!flagA){  
  114.   
  115.             pthread_mutex_unlock(&mutex);  
  116.             usleep(30);  
  117.             //          printf("--------------------------wait flagA\n");  
  118.             pthread_mutex_lock(&mutex);  
  119.         }  
  120.         /*循环结束表示A在等待,所以发信号给A*/  
  121.   
  122.         //      printf("signal C--->A finished!\n");  
  123.         pthread_cond_signal(&condC_A);        
  124.         pthread_mutex_unlock(&mutex);  
  125.         //      printf("%c UNLOCK!\n",*name);  
  126.   
  127.         i++;  
  128.         usleep(20);  
  129.     }  
  130. }  
  131.   
  132. int main(void){  
  133.   
  134.     pthread_t th1,th2,th3;  
  135.   
  136.     char name1 = 'A',name2 = 'B',name3 = 'C';  
  137.   
  138.     int *p1 =(int *) &name1;  
  139.     int *p2 =(int *) &name2;  
  140.     int *p3 =(int *) &name3;  
  141.   
  142.     if(pthread_create(&th1,NULL,th_A_C,(void *)p1) < 0){  
  143.   
  144.         fprintf(stderr,"pthread_create th1 %s\n",strerror(errno));  
  145.         exit(1);  
  146.     }  
  147.     usleep(30);  
  148.     if(pthread_create(&th2,NULL,th_B_A,(void *)p2) < 0){  
  149.   
  150.         fprintf(stderr,"pthread_create th2 %s\n",strerror(errno));  
  151.         exit(1);  
  152.     }  
  153.     usleep(30);  
  154.     if(pthread_create(&th3,NULL,th_C_B,(void *)p3) < 0){  
  155.   
  156.         fprintf(stderr,"pthread_create th1 %s\n",strerror(errno));  
  157.         exit(1);  
  158.     }  
  159.   
  160.     //起始给线程A发通知,防止A,b,c,死锁  
  161.     /*直接通知A,不能内个让他再傻等*/  
  162.   
  163.     pthread_cond_broadcast(&condC_A);  
  164.   
  165.   
  166.     pthread_join(th1,NULL);  
  167.     printf("th1 finished!\n");  
  168.     pthread_join(th2,NULL);  
  169.     printf("th2 finished!\n");  
  170.     pthread_join(th3,NULL);  
  171.     printf("th3 finished!\n");  
  172.   
  173.     return 0;  
  174. }  
  175. </pthread></stdlib></string></errno></stdio>  

程序顺利执行,结果正确。但是代码冗余很大,可扩展性不好,在下面做改进。。


改进版的, 把A,B,C先程中的大量重复部分封装成一个函数,用循环创建和回收线程。 

[c] view plaincopy
  1.    
  2. #include<stdio.h>  
  3. #include<errno.h>  
  4. #include<string.h>  
  5. #include<stdlib.h>  
  6. #include<pthread.h>  
  7.   
  8. #define PRINTTIME 10  
  9. /*互斥锁 MUTEX*/  
  10. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  
  11. /*条件变量*/  
  12. pthread_cond_t condA_B = PTHREAD_COND_INITIALIZER;  
  13. pthread_cond_t condB_C = PTHREAD_COND_INITIALIZER;  
  14. pthread_cond_t condC_A = PTHREAD_COND_INITIALIZER;  
  15.   
  16. int flagA = 0,flagB = 0,flagC = 0;  
  17.   
  18. void pthread_print(pthread_cond_t *cond_wait,char *name,int *flag_self,int *flag_wait,pthread_cond_t *cond_signal){  
  19.   
  20.     printf("%c come!\n",*name);  
  21.     int i = 0;  
  22.     while(i < PRINTTIME){  
  23.         pthread_mutex_lock(&mutex);  
  24.         *flag_self = 1;  
  25.   
  26.         pthread_cond_wait(cond_wait,&mutex);                                      
  27.         *flag_self = 0;                                                       
  28.         printf("%c:%d-->%lx\n",*name,i,pthread_self());                    
  29.   
  30.         while(!(*flag_wait)){                                         
  31.   
  32.             pthread_mutex_unlock(&mutex);  
  33.             usleep(30);  
  34.             pthread_mutex_lock(&mutex);  
  35.   
  36.         }/*循环结束表示flagBC为1,就是B已经加锁,并在等待A给它信号,所以现在A发信号给B*/  
  37.   
  38.         pthread_cond_signal(cond_signal);                             
  39.         pthread_mutex_unlock(&mutex);  
  40.         i++;  
  41.         usleep(20);  
  42.     }  
  43. }  
  44.   
  45. void *th_A_C(void *arg){  
  46.   
  47.     char *name = (char *)arg;  
  48.     pthread_print(&condC_A,name,&flagA,&flagB,&condA_B);  
  49.     flagA = 1;/*防止C 等待 A 而不能结束*/  
  50. }  
  51.   
  52.   
  53.   
  54. void *th_B_A(void *arg){  
  55.   
  56.     char *name = (char *)arg;  
  57.     pthread_print(&condA_B,name,&flagB,&flagC,&condB_C);  
  58. }  
  59.   
  60.   
  61.   
  62. void *th_C_B(void *arg){  
  63.     char *name = (char *)arg;  
  64.     pthread_print(&condB_C,name,&flagC,&flagA,&condC_A);  
  65.   
  66. }  
  67.   
  68. int main(void){  
  69.   
  70.   
  71.     char name1 = 'A',name2 = 'B',name3 = 'C';  
  72.   
  73.     char  *p[] = {  
  74.   
  75.         (char *) &name1,  
  76.         (char *) &name2,  
  77.         (char *) &name3  
  78.     };  
  79.   
  80.   
  81.     void *(*th_funs[])(void *) = {  
  82.   
  83.         th_A_C,  
  84.         th_B_A,  
  85.         th_C_B  
  86.   
  87.     };  
  88.   
  89.     int count = sizeof(th_funs)/sizeof(th_funs[0]);  
  90.     pthread_t th[count];  
  91.     int i = 0;  
  92.     while(i < count){  
  93.         if(pthread_create(&th[i],NULL,th_funs[i],(void *)p[i]) < 0){  
  94.   
  95.             fprintf(stderr,"pthread_create th1 %s\n",strerror(errno));  
  96.             exit(1);  
  97.         }  
  98.         usleep(30);  
  99.         i++;  
  100.     }  
  101.   
  102.     pthread_cond_broadcast(&condC_A);  
  103.   
  104.     for(i = 0;i < count;i++){  
  105.         pthread_join(th[i],NULL);  
  106.         printf("th%d finished!\n",i);  
  107.     }  
  108.   
  109.     return 0;  
  110. }  
  111. </pthread></stdlib></string></errno></stdio>  

上一个封装的不好,最后一个版本老师给的,封装的更好一些:

[c] view plaincopy
  1.    
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <string.h>  
  5. #include <errno.h>  
  6. #include <pthread.h>  
  7.   
  8. #define LP_TIMES    10  
  9.   
  10. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  
  11.   
  12. pthread_cond_t cond_AB = PTHREAD_COND_INITIALIZER;  
  13. pthread_cond_t cond_BC = PTHREAD_COND_INITIALIZER;  
  14. pthread_cond_t cond_CA = PTHREAD_COND_INITIALIZER;  
  15.   
  16. //标记  
  17. int flag_AB,flag_BC,flag_CA;  
  18.   
  19. //标记检查的线程等待  
  20. void th_condflag_wait(int *flag,pthread_cond_t *cond,pthread_mutex_t *mutex)  
  21. {  
  22.     (*flag) = 1;  
  23.     pthread_cond_wait(cond,mutex);  
  24.     (*flag) = 0;  
  25. }  
  26.   
  27. //标记检查的线程通知  
  28. void th_condflag_broadcast(int *flag,pthread_cond_t *cond,pthread_mutex_t *mutex)  
  29. {  
  30.     while(!(*flag))  
  31.     {  
  32.         pthread_mutex_unlock(mutex);  
  33.         usleep(50);  
  34.         pthread_mutex_lock(mutex);  
  35.     }  
  36.     pthread_cond_broadcast(cond);  
  37. }  
  38.   
  39. void *th_fun_A(void *arg)  
  40. {  
  41.     int i = LP_TIMES;  
  42.     while(i--)  
  43.     {  
  44.         pthread_mutex_lock(&mutex);  
  45.         //A wait C  
  46.         th_condflag_wait(&flag_CA,&cond_CA,&mutex);  
  47.           
  48.         printf("A%d: %lx\n",10-i,pthread_self());  
  49.           
  50.         //A cond B  
  51.         th_condflag_broadcast(&flag_AB,&cond_AB,&mutex);  
  52.         pthread_mutex_unlock(&mutex);  
  53.           
  54.         usleep(50);  
  55.     }  
  56.     //防止C线程最后一次等待A线程时死锁  
  57.     flag_CA = 1;  
  58. }  
  59.   
  60. void *th_fun_B(void *arg)  
  61. {  
  62.     int i = LP_TIMES;  
  63.     while(i--)  
  64.     {  
  65.         pthread_mutex_lock(&mutex);  
  66.         //B wait A  
  67.         th_condflag_wait(&flag_AB,&cond_AB,&mutex);  
  68.   
  69.         printf("B%d: %lx\n",10-i,pthread_self());  
  70.           
  71.         //B cond C  
  72.         th_condflag_broadcast(&flag_BC,&cond_BC,&mutex);  
  73.         pthread_mutex_unlock(&mutex);  
  74.   
  75.         usleep(50);  
  76.     }  
  77. }  
  78.   
  79. void *th_fun_C(void *arg)  
  80. {  
  81.     int i = LP_TIMES;  
  82.     while(i--)  
  83.     {  
  84.         pthread_mutex_lock(&mutex);  
  85.         //C wait B  
  86.         th_condflag_wait(&flag_BC,&cond_BC,&mutex);  
  87.   
  88.         printf("C%d: %lx\n",10-i,pthread_self());  
  89.           
  90.         //C cond A  
  91.         th_condflag_broadcast(&flag_CA,&cond_CA,&mutex);  
  92.         pthread_mutex_unlock(&mutex);  
  93.         usleep(50);  
  94.     }  
  95. }  
  96.   
  97. int main(void)  
  98. {  
  99.     printf("main: %lx\n",pthread_self());  
  100.   
  101.     //保存3个线程的处理函数  
  102.     void *(*th_funs[])(void *) =   
  103.     {  
  104.         th_fun_A,  
  105.         th_fun_B,  
  106.         th_fun_C  
  107.     };  
  108.   
  109.     int th_count = sizeof(th_funs)/sizeof(th_funs[0]);  
  110.   
  111.     pthread_t th[th_count];  
  112.     int i;  
  113.     for(i = 0;i < th_count;i++)  
  114.     {  
  115.         //通过线程函数数组记录的函数来创建线程  
  116.         if(pthread_create(th+i,NULL,th_funs[i],(void *)i) < 0)  
  117.         {  
  118.             fprintf(stderr,"th_create: %s\n",  
  119.                     strerror(errno));  
  120.             exit(1);  
  121.         }  
  122.         printf("th[%d]: %lx\n",i,th[i]);  
  123.     }  
  124.   
  125.     //起始给A线程发出通知,防止A和C死锁  
  126.     pthread_mutex_lock(&mutex);  
  127.     th_condflag_broadcast(&flag_CA,&cond_CA,&mutex);  
  128.     pthread_mutex_unlock(&mutex);  
  129.   
  130.     //回收线程  
  131.     for(i = 0;i < th_count;i++)  
  132.     {  
  133.         pthread_join(th[i],NULL);  
  134.         printf("i: %d finished!\n",i);  
  135.     }  
  136.   
  137.     return 0;  
  138. }  
  139.   

  1. </pthread></errno></string></stdlib></stdio>  

转载的http://blog.csdn.net/baiding1123/article/details/14053957

0 0
原创粉丝点击