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

分析:

  1. 当使用broadcast方式时,两个被阻塞的线程都被唤醒了,被唤醒的线程将变为pthread_mutex_lock(mutex1)的状态,他们将抢着对mutex1加锁,在本次运行过程中thread_1加锁成功了,thread_2没有成功抢到锁,于是它就被阻塞了,在thread_1执行完毕释放锁后,会通知所有被阻塞在mutex1上的线程,于是thread_2最终成功拿到了锁,然后顺利执行。
  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的效果

 

 分析:

  1. 当使用broadcast方式时,因为两个线程都被唤醒了,且它们想要加的锁并没有竞争关系,因此它们是并发执行的,而不必像前一种情况中那样必须一前一后执行。
  2. 当使用signal方式时,只被唤醒了一个线程,因此只有一个线程成功执行。

  

posted @ 2019-11-14 10:44  机智的小小帅  阅读(4826)  评论(1编辑  收藏  举报