zoukankan      html  css  js  c++  java
  • [转] 条件变量(Condition Variable)详解

    http://www.wuzesheng.com/?p=1668

    条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法。举个简单的例子,应用程序A中包含两个线程t1和t2。t1需要在 bool变量test_cond为true时才能继续执行,而test_cond的值是由t2来改变的,这种情况下,如何来写程序呢?可供选择的方案有两 种:

    • 第一种是t1定时的去轮询变量test_cond,如果test_cond为false,则继续休眠;如果test_cond为true,则开始执行。
    • 第二种就是上面提到的条件变量,t1在test_cond为false时调用cond_wait进行等待,t2在改变test_cond的值后,调用cond_signal,唤醒在等待中的t1,告诉t1 test_cond的值变了,这样t1便可继续往下执行。

    很明显,上面两种方案中,第二种方案是比较优的。在第一种方案中,在每次轮询时,如果t1休眠的时间比较短,会导致cpu浪费很厉害;如果t1休眠的时间 比较长,又会导致应用逻辑处理不够及时,致使应用程序性能下降。第二种方案就是为了解决轮询的弊端而生的。然而条件变量在使用的过程中,比较容易出错,如 何用得不正确的话,会适得其反的,接下来,我将详细分析如何来使用条件变量,希望能够给在使用条件变量过程中遇到问题的朋友有所帮助。
    在开始介绍之前,需要说明一下,在接下来的介绍中,需要用到互斥锁和条件变量相关的内容,在这里我以linux下的pthread_mutex_t为互斥 锁类型,pthread_cond_t为条件变量类型来进行介绍,对pthread不熟的朋友,可以参考一下linux下的manual。
    1. 下面是把刚开始举的例子翻译后的程序:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    pthread_mutex_t mutex;  ///< 互斥锁
    pthread_cond_t  cond;   ///< 条件变量
    bool test_cond = false;
    /// TODO 初始化mutex和cond
     
    /// thread 1:
    pthread_mutex_lock(&mutex);            ///< 1
    while (!test_cond)
    {
        pthread_cond_wait(&cond, &mutex);  ///< 2,3
    }
    pthread_mutex_unlock(&mutex);          ///< 4
    RunThread1Func();
     
    /// thread 2:
    pthread_mutex_lock(&mutex);            ///< 5
    test_cond = true;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);          ///< 6
     
    /// TODO 销毁mutex和cond

    通过上面的例子,下面我来介绍一下条件变量在使用过程中需要注意的几点(也是比较容易出错的):
    (1)条件变量的使用过程中,最为关键的一点是互斥锁的使用。细心的朋友应该发现了,我在上面的例子中标了1、2、3、4、5、6个标号。在这里1、4、 5、6都是正常的lock/unlock,2、3是需要特别说明的。2是进入pthread_cond_wait后 的,pthread_cond_wait调的pthread_mutex_unlock,这样做的目的是为了保证在thread1阻塞wait 后,thread2获取同一把锁mutex的时候,能够正常获取(即5,6)。3是thread1被唤醒后,要退出pthead_cond_wait之 前,pthread_cond_wait调的pthread_mutex_lock,这样做的目的是为了把mutex的控制权还给调用 pthread_cond_wait的线程(即thread1)。整理一下基本的时序为:

    1
    2
    3
    
    thread 1 lock->thread 1 wait-> thread 1 unlock(in wait)
    ->thread 2 lock->thread 2 signal->thread 2 unlock
    ->thread 1 lock(in wait)->thread 1 unlock

    (2)条件变量使用的过程中,通常会加一个bool或者int的值test_cond来配合使用。这里需要注意的一点是一定要在signal之前来 改变test_cond,这样才能保证wait的线程被唤醒后,能够取到正确的test_cond的值,否则后果是不可预测的。

  • 相关阅读:
    Azkaban的使用
    Azkaban安装
    Kafka 启动失败,报错Corrupt index found以及org.apache.kafka.common.protocol.types.SchemaException: Error reading field 'version': java.nio.BufferUnderflowException
    Kafka 消费者设置分区策略及原理
    Kafka利用Java API自定义生产者,消费者,拦截器,分区器等组件
    zookeeper群起总是有那么几个节点起不来的问题解决
    flume 启动agent报No appenders could be found for logger的解决
    Flume 的监控方式
    Flume 自定义 组件
    Source r1 has been removed due to an error during configuration java.lang.IllegalArgumentException: Required parameter bind must exist and may not be null & 端口无法连接
  • 原文地址:https://www.cnblogs.com/qiangxia/p/4293088.html
Copyright © 2011-2022 走看看