• 深入Phtread(三):线程的同步Condition Variables


    深入Phtread(三):线程的同步-Condition Variables


        继续昨天的线程同步,条件变量(Condition Variables)是用于线程间,通信共享数据状态改变的机制。

    简介

        当线程互斥地访问一些共享的状态时,往往会有些线程需要等到这些状态改变后才应该继续执行。如:有一个共享的队列,一个线程往队列里面插入数据,另一个线程从队列中取数据,当队列为空的时候,后者应该等待队列里面有值才能取数据。而共享数据(队列)应该用mutex来保护,为了检查共享数据的状态(队列是否为空),线程必须先锁定mutex,然后检查,最后解锁mutex。
     
        问题出来了:当另外一个线程B锁定mutex后,往队列里面插入了一个值,B并不知道A在等着它往队列里面放入一个值。,线程A(等待状态改变)一直在运行,线程B可能已经检查过队列是空的,并不知道队列里已经有值了,所以一直阻塞着自己。为了解决这样的问题引入了条件变量机制。线程B等待于一个条件变量,当线程A插入了一个值后,signal或broadcast这个条件变量,通知线程B状态已改变,A发现条件变量被signaled了,就继续执行。就这样,当一个线程改变共享数据状态后,可以及时通知那些等待于该状态的线程。图示下:
     

        中间的矩形代表条件变量,当线程线位于矩形内,表示线程等待该条件变量。位于中心线下下方,则表示signal了该条件变量。
        开始线程1 signal 了条件变量,由于没有其他线程等待于该条件变量,所以没什么效果。然后,线程1和线程2先后等待该条件变量,过了一会,线程3 signal了条件变量,线程3的信号解除了线程1的阻塞。然后,线程3等待该条件变量。最后线程1 broadcast了该条件变量,同时解除了等待于条件变量的线程1和线程2。
     


    条件变量的创建和销毁

    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    int pthread_cond_init(pthread_cond_t* cond, pthread_condattr_t* condattr);
    int pthread_cond_destroy(pthread_cond_t* cond);
     
    和互斥量一样,可以动态创建和静态创建。
    静态创建:条件变量声明为extern或static变量时。
    例程:
     
    动态创建:一般情况下,条件变量要和它的判定条件定义在一起,此时若包含该条件变量的数据动态创建了,则条件变量也需要动态创建,不过记得不用时用pthread_cond_destroy销毁。
     
    例程:
     

    等待条件变量

    int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);
    int pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, struct timespec* expiration);
     
        条件变量与互斥量一起使用,调用pthread_cond_wait或pthread_cond_timedwait时,记得在前面锁定mutex,尽可能多的判断判定条件。上面提到的两个等待条件变量的函数,显示解锁mutex,然后阻塞线程等待状态改变,等待的条件变量signaled后,锁定mutex,返回。记着,这两个函数返回时,mutex一定是锁定的。
     
    多个条件变量可以共享一个互斥变量,相反则不成立。
     
    例程:
     

    唤醒等待条件变量的线程

     
    int pthread_cond_signal(pthread_cond_t* cond);
    int pthread_cond_broadcast(pthread_cond_t* cond);
     
        一但有线程由于某些判定条件(predicate)没满足,等待条件变量。我们就有必要当条件满足时,发送信号去唤醒这些线程。
        注意:broadcast通常很容易被认为是signal的通用版,其实不能这样理解,准确一点应该说,signal是broadcast的优化版。具体区别不大,但signal效率较broadcast高些。但你不确信有几个线程等待条件变量时用broadcast(When in doubt, broadcast!)。
     
    例程:

     

  • 相关阅读:
    A05. openstack架构实战-nova服务控制节点安装
    A04. openstack架构实战-glance服务安装
    A03. openstack架构实战-keystone安装
    SSH暴力破解的解读与防御
    tcpdump抓包命令使用
    Superspeed.sh 一键测试服务器到中国上传/下载速度
    Windows ping TCP端口工具之tcping
    实验验证centos 7 系统不会缓存dns信息
    Linux下的TCP测试工具——TCPING安装简明教程
    Debian 9.12 live系统密码重置
  • 原文地址:https://www.cnblogs.com/mywolrd/p/1930700.html
Copyright © 2020-2023  润新知