多线程交替打印ABC的Linux C/C++实现

时间:2021-12-25 08:23:24

1. 题目:

建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。

2.直接上代码先, 其中涉及的知点随后再补:

  1 //
  2 // Target: 
  3 // Create three threads with name A, B, C respectively. Please output the thread name 10 times to the terminal.
  4 // We want the thread names was printed by turns. 
  5 // Please let the three threads are all in running status and output(thread name ABCABCABC) by turns. 
  6 //
  7 // Time: April,4 2018
  8 // Author: 
  9 // Version : 
 10 
 11 #include <pthread.h>   
 12 #include <iostream>   
 13 #include <cstdio>   
 14 
 15 #define LOG 0
 16 const int THREAD_NUMBER = 3;  
 17   
 18 // Thread mutex and condition variables.
 19 pthread_mutex_t thread_mutex[THREAD_NUMBER];  
 20 pthread_cond_t thread_cond[THREAD_NUMBER];  
 21   
 22 // Is thread waiting..
 23 bool thread_wait_flag[THREAD_NUMBER];  
 24 
 25 int iName[THREAD_NUMBER]; // Thread argument for buffering every threadName. 
 26 
 27 // Flag to indicates which thread gets the turn to output its id.
 28 pthread_mutex_t mutex;  
 29 int thread_turn;  
 30   
 31 void *thread_func(void *arg);  
 32   
 33 int main(int argc, char **argv)  
 34 {  
 35     pthread_t tids[THREAD_NUMBER];  
 36   
 37     for (int i = 0; i < THREAD_NUMBER; ++i)  
 38     {  
 39         pthread_mutex_init(&thread_mutex[i], NULL);  
 40         pthread_cond_init(&thread_cond[i], NULL);  
 41     }  
 42       
 43     pthread_mutex_init(&mutex, NULL);  
 44     thread_turn = 0;  
 45       
 46     for (int i = 0; i < THREAD_NUMBER; ++i)  
 47         thread_wait_flag[i] = false;  
 48       
 49     for (int i = 0; i < THREAD_NUMBER; ++i)  
 50     {  
 51         iName[i] = i; //The thread argument should be isolated between threeads.
 52         pthread_create(&tids[i], NULL, thread_func, (void *)&iName[i]);  
 53     }  
 54   
 55     for (int i = 0; i < THREAD_NUMBER; ++i)  
 56     {  
 57         pthread_join(tids[i], NULL);  
 58     }  
 59     printf("\n");  
 60     return 0;  
 61 }  
 62   
 63 void *thread_func(void *arg)  
 64 {  
 65     int *pid = (int*)arg;
 66     int id = *pid;
 67     char ch = 'A' + id;  
 68     int count = 0;  
 69 #if LOG
 70     printf("Thread:%d starts running.\n", id);  
 71 #endif
 72     while (true)  
 73     {  
 74         if (id == thread_turn) // output thread id and send signal.
 75         {  
 76 #if LOG
 77             printf("Thread:%d starts Printing.\n", id);  
 78 #endif
 79             printf(" %c ", ch);  
 80             ++count;  
 81             if (id == THREAD_NUMBER-1 && count == 10) // exit if it's the third thread.
 82                 break;  
 83             else if (id == THREAD_NUMBER - 1)
 84                 printf("\n");
 85 
 86             pthread_mutex_lock(&mutex);  
 87 #if LOG
 88             printf("Thread:%d get the global mutex.\n", id);  
 89 #endif
 90             thread_turn++;  
 91             thread_turn %= THREAD_NUMBER;  
 92             pthread_mutex_unlock(&mutex);  
 93 #if LOG
 94             printf("Thread:%d release the global mutex.\n", id);  
 95 #endif              
 96             while (true)  
 97             {  
 98                 pthread_mutex_lock(&thread_mutex[thread_turn]);  
 99                 if (true == thread_wait_flag[thread_turn])  
100                 {  
101                     pthread_cond_signal(&thread_cond[thread_turn]);  
102                     pthread_mutex_unlock(&thread_mutex[thread_turn]);  
103                     break;  
104                 }  
105                 pthread_mutex_unlock(&thread_mutex[thread_turn]);  
106             }  
107             if (count == 10) // Thread will exit after send signal if the thread number is 1 or 2.
108                 break;  
109         }  
110         else // wait  
111         {  
112 #if LOG
113             printf("Thread:%d is waiting.\n", id);  
114 #endif
115             pthread_mutex_lock(&thread_mutex[id]);  
116             thread_wait_flag[id] = true;  
117             pthread_cond_wait(&thread_cond[id], &thread_mutex[id]);  
118             thread_wait_flag[id] = false;  
119             pthread_mutex_unlock(&thread_mutex[id]);  
120         }  
121     }  
122     return (void *)0;  
123 }  

line 90: 将thread_turn加1,这将会使另一个在等待中的线程获得打印顺序.

98~105: 检测因等待thread_turn而处于阻塞状态的线程, 并调用pthread_cond_signal()发送信号使相应的线程从cond_wait队列移转移到mutex_lock,并唤醒.

第98行将互斥量thread_mutex[thread_turn]加锁,同时检测所对应的线程等待标志是否为true;若为true, 则使用pthread_cond_singal()函数唤醒因调用pthread_cond_wait()阻塞的线程.并在下一句中释放互斥量thread_mutex[thread_turn].

115~119: 如果本线程未获得打印顺序, 第116行会将等待标志设置为true, 并调用pthread_cond_wait() ,使当前线程挂起. 等待相应的pthread_cond_signal()调用时再唤醒.

pthread_cond_wait(&thread_cond[id], &thread_mutex[id]);  会将thread_mutext[id]解锁, 并将thread_cond[id]加锁,然后线程挂起. 等待信号唤醒.

3. 运行结果

多线程交替打印ABC的Linux C/C++实现