pthread_cond_broadcast(&cond1)的作用是喚醒所有正在pthread_cond_wait(&cond1,&mutex1)的線程。
pthread_cond_signal(&cond1)的的作用是喚醒所有正在pthread_cond_wait(&cond1,&mutex1)的至少一個線程。(雖然我還沒碰到過多於一個線程的情況,但是man幫組手冊上說的是至少一個)
下面分為情況討論一下這兩個函數的效果。
第一種情況:多個線程等待同一個cond,並且想對同一個mutex加鎖。
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <pthread.h> 4 #include <stdlib.h> 5 6 pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 7 pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; 8 pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; 9 10 void* thread_task1(void* arg) 11 { 12 pthread_mutex_lock(&mutex1); 13 14 pthread_cond_wait(&cond,&mutex1); 15 16 printf("thread_task1 start working\n"); 17 sleep(2); 18 printf("thread_task1 works over\n"); 19 pthread_mutex_unlock(&mutex1); 20 21 return NULL; 22 23 24 25 } 26 27 void* thread_task2(void* arg) 28 { 29 pthread_mutex_lock(&mutex2); 30 31 pthread_cond_wait(&cond,&mutex2); 32 33 printf("thread_task2 start working\n"); 34 sleep(2); 35 printf("thread_task2 works over\n"); 36 pthread_mutex_unlock(&mutex2); 37 38 return NULL; 39 40 41 } 42 43 void* broadcastDiffMutex(void* arg) 44 { 45 pthread_cond_broadcast(&cond); 46 return NULL; 47 48 } 49 50 void* signalDiffMutex(void* arg) 51 { 52 pthread_cond_signal(&cond); 53 return NULL; 54 55 } 56 57 int main() 58 { 59 pthread_t thread_1,thread_2,thread_3; 60 pthread_create(&thread_1,NULL,thread_task1,NULL); 61 pthread_create(&thread_2,NULL,thread_task2,NULL); 62 sleep(2); 63 64 #ifdef SIGNAL 65 pthread_create(&thread_3,NULL,signalDiffMutex,NULL); 66 #else 67 pthread_create(&thread_3,NULL,broadcastDiffMutex,NULL); 68 #endif 69 70 71 pthread_join(thread_1,NULL); 72 pthread_join(thread_2,NULL); 73 pthread_join(thread_3,NULL); 74 75 return 0; 76 77 }
使用broadcast的運行結果:
使用signal的運行結果:
分析:
- 當使用broadcast方式時,兩個被阻塞的線程都被喚醒了,被喚醒的線程將變為pthread_mutex_lock(mutex1)的狀態,他們將搶着對mutex1加鎖,在本次運行過程中thread_1加鎖成功了,thread_2沒有成功搶到鎖,於是它就被阻塞了,在thread_1執行完畢釋放鎖后,會通知所有被阻塞在mutex1上的線程,於是thread_2最終成功拿到了鎖,然后順利執行。
- 當使用signal方式時,thread_1和thread_2中只被喚醒了一個線程,在本次運行中是thread_1被喚醒了,而因為thread_2沒有被喚醒,他就一直卡在pthread_cond_wait處呼呼大睡,所以最終只有thread_1執行完畢。
第二種情況:多個線程等待同一個cond,並且分別不同的mutex加鎖。
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <pthread.h> 4 #include <stdlib.h> 5 6 pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 7 pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; 8 pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; 9 10 void* thread_task1(void* arg) 11 { 12 pthread_mutex_lock(&mutex1); 13 14 pthread_cond_wait(&cond,&mutex1); 15 16 printf("thread_task1 start working\n"); 17 sleep(2); 18 printf("thread_task1 works over\n"); 19 pthread_mutex_unlock(&mutex1); 20 21 return NULL; 22 23 24 25 } 26 27 void* thread_task2(void* arg) 28 { 29 pthread_mutex_lock(&mutex2); 30 31 pthread_cond_wait(&cond,&mutex2); 32 33 printf("thread_task2 start working\n"); 34 sleep(2); 35 printf("thread_task2 works over\n"); 36 pthread_mutex_unlock(&mutex2); 37 38 return NULL; 39 40 41 } 42 43 void* broadcastDiffMutex(void* arg) 44 { 45 pthread_cond_broadcast(&cond); 46 return NULL; 47 48 } 49 50 void* signalDiffMutex(void* arg) 51 { 52 pthread_cond_signal(&cond); 53 return NULL; 54 55 } 56 57 int main() 58 { 59 pthread_t thread_1,thread_2,thread_3; 60 pthread_create(&thread_1,NULL,thread_task1,NULL); 61 pthread_create(&thread_2,NULL,thread_task2,NULL); 62 sleep(2); 63 64 #ifdef SIGNAL 65 pthread_create(&thread_3,NULL,signalDiffMutex,NULL); 66 #else 67 pthread_create(&thread_3,NULL,broadcastDiffMutex,NULL); 68 #endif 69 70 71 pthread_join(thread_1,NULL); 72 pthread_join(thread_2,NULL); 73 pthread_join(thread_3,NULL); 74 75 return 0; 76 77 }
使用broadcast的效果:
使用signal的效果
分析:
- 當使用broadcast方式時,因為兩個線程都被喚醒了,且它們想要加的鎖並沒有競爭關系,因此它們是並發執行的,而不必像前一種情況中那樣必須一前一后執行。
- 當使用signal方式時,只被喚醒了一個線程,因此只有一個線程成功執行。