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. 运行结果