pthread_cond_broadcast & pthread_cond_signal
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(&mutex1); 30 31 pthread_cond_wait(&cond,&mutex1); 32 33 printf("thread_task2 start working\n"); 34 sleep(2); 35 printf("thread_task2 works over\n"); 36 pthread_mutex_unlock(&mutex1); 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方式时,只被唤醒了一个线程,因此只有一个线程成功执行。