• 条件变量(一)


    互斥器mutex用来排他性的访问共享数据,他不是等待原语。若要等待某个条件成立,我们应该使用条件变量(condition variable)。条件变量顾名思义就是一个或多个线程等待某个布尔表达式为真,即等待别的线程唤醒它。

    条件变量只有一种使用方式,wait端:

    1、必须与Mutex一起使用,以保护布尔表达式的读写收到保护。

    2、Mutex上锁后才能调用wait()等待。

    3、把wait()放到 while循环内,而不是if语句块内。否则会导致假唤醒。

    对于条件变量,我的简单理解就是消费者和生产者:notify一段为生产者,告诉wait端有元素可以消费了。我在项目中最长遇到的就是将其用到BlockingQueue中。下面是简单的实现:

    生产者, 将元素去出队列:

    1 void enqueue(T t)
    2 {
    3      std::lock_guard<std::mutex> lock(m);
    4      q.push_back(t);
    5      c.notify_one();
    6 }

    消费者,将T value放入队列:

     1 T dequeue(T &value)
     2 {
     3     std::unique_lock<std::mutex> lock(m);
     4     while (q.empty()) {     //必须使用循环,必须在判断后再wait()
     5         c.wait();
     6     }
     7     value = q.front();
     8     q.pop();
     9     return value;
    10 }

    第五行代码c.wait()会把线程投入睡眠,并释放线程持有的互斥锁,当wait()返回时,该再次上锁,该线程再次持有该互斥锁。(这个怎么做到的?释放互斥锁,然后睡眠期间,该锁不会被别的线程持有吗?)

    注意:一定要使用循环判断queue是否有元素可用,才调能用c.wait()。不然可能产生假唤醒。因为notify_one(调用的是pthread_cond_signal)或者notify_all(调用的是pthread_cond_broadcast)都只能唤醒正在wait()的线程,这就是所谓的边沿触发。 

    注:本文参考http://www.cppblog.com/Solstice/archive/2015/10/30/203094.html

  • 相关阅读:
    EntytyFramework批量更新
    EntityFramework批量Insert
    asp.net MVC Session锁的问题
    谈谈ThreadStatic
    C#中XmlSerializer的内存占用问题
    转:【译】Asp.net MVC 利用自定义RouteHandler来防止图片盗链
    面试心得
    Part 39 AngularJS route change events
    Part 38 AngularJS cancel route change
    Part 37 Difference between $scope and $rootScope
  • 原文地址:https://www.cnblogs.com/howo/p/8552916.html
Copyright © 2020-2023  润新知