zoukankan      html  css  js  c++  java
  • 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
    ");
    17     sleep(2);
    18     printf("thread_task1 works over
    ");
    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
    ");
    34     sleep(2);
    35     printf("thread_task2 works over
    ");
    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
    ");
    17     sleep(2);
    18     printf("thread_task1 works over
    ");
    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
    ");
    34     sleep(2);
    35     printf("thread_task2 works over
    ");
    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方式时,只被唤醒了一个线程,因此只有一个线程成功执行。

      

  • 相关阅读:
    第一节:SpringMVC概述
    SpringMVC【目录】
    Windows 系统快速查看文件MD5
    (error) ERR wrong number of arguments for 'hmset' command
    hive使用遇到的问题 cannot recognize input
    Overleaf支持的部分中文字体预览
    Understanding and Improving Fast Adversarial Training
    Django2实战示例 第十三章 上线
    Django2实战示例 第十二章 创建API
    Django2实战示例 第十一章 渲染和缓存课程内容
  • 原文地址:https://www.cnblogs.com/XiaoXiaoShuai-/p/11855408.html
Copyright © 2011-2022 走看看