pthread_cond_broadcast & pthread_cond_signal

pthread_cond_broadcast(&cond1)的作用是唤醒所有正在pthread_cond_wait(&cond1,&mutex1)的线程。

pthread_cond_signal(&cond1)的的作用是唤醒所有正在pthread_cond_wait(&cond1,&mutex1)的其中一个线程。

下面分为情况讨论一下这两个函数的效果。

第一种情况:多个线程等待同一个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 
 9 void* thread_task1(void* arg)
10 {
11     pthread_mutex_lock(&mutex1);
12 
13     pthread_cond_wait(&cond,&mutex1);
14 
15     printf("thread_task1 start working\n");
16     sleep(2);
17     printf("thread_task1 works over\n");
18     pthread_mutex_unlock(&mutex1);
19 
20     return NULL;
21 
22 
23 }
24 
25 void* thread_task2(void* arg)
26 {
27     pthread_mutex_lock(&mutex1);
28 
29     pthread_cond_wait(&cond,&mutex1);
30 
31     printf("thread_task2 start working\n");
32     sleep(2);
33     printf("thread_task2 works over\n");
34     pthread_mutex_unlock(&mutex1);
35 
36     return NULL;
37 
38 }
39 
40 void* broadcastSameMutex(void* arg)
41 {
42     pthread_cond_broadcast(&cond);
43     return NULL;
44 }
45 
46 void* signalSameMutex(void* arg)
47 {
48     pthread_cond_signal(&cond);
49     return NULL;
50 }
51 
52 int main()
53 {
54     pthread_t thread_1,thread_2,thread_3;
55     pthread_create(&thread_1,NULL,thread_task1,NULL);
56     pthread_create(&thread_2,NULL,thread_task2,NULL);
57     sleep(2);
58 
59 #ifdef SIGNAL
60     pthread_create(&thread_3,NULL,signalSameMutex,NULL);
61 #else
62     pthread_create(&thread_3,NULL,broadcastSameMutex,NULL);
63 #endif
64 
65 
66     pthread_join(thread_1,NULL);
67     pthread_join(thread_2,NULL);
68     pthread_join(thread_3,NULL);
69 
70     pthread_mutex_destroy(&mutex1);
71     pthread_cond_destroy(&cond);
72     return 0;
73 
74 }

使用broadcast的运行结果:

 使用signal的运行结果:

分析:

  1. 当使用broadcast方式时,两个被阻塞的线程都被唤醒了,被唤醒的线程想做的第一件事就是对mutex1加锁,在本次运行过程中thread_1加锁成功了,虽然thread_2没有成功抢到锁,但是它也没有闲着,它一直在尝试对mutex1进行加锁,皇天不负有心人,在thread_1执行完毕释放锁后,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     pthread_mutex_destroy(&mutex1);
76     pthread_mutex_destroy(&mutex2);
77     pthread_cond_destroy(&cond);
78     return 0;
79 
80 }

使用broadcast的效果:

使用signal的效果

 分析:

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

  

猜你喜欢

转载自www.cnblogs.com/XiaoXiaoShuai-/p/11855408.html