条件include_C++11(六) 条件变量(condition_variable)

前面提到了线程,那么肯定就要说到条件变量。

条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待

条件变量的条件成立而挂起;另一个线程使条件成立(给出条件成立信号)。为了防止竞争,条件变

量的使用总是和一个互斥量结合在一起。

头文件

  • condition_variable

  • condition_variable_any

相同点:两者都能与std::mutex一起使用。

不同点:前者仅限于与 std::mutex  一起工作,而后者可以和任何满足最低标准的互斥量一

起工作,从而加上了_any的后缀。condition_variable_any会产生额外的开销。

一般只推荐使用condition_variable。除非对灵活性有硬性要求,才会考虑condition_variable_any。

条件变量的构造函数:

std::condition_variable::condition_variableconstructor:    condition_variable();   //默认构造函数无参    condition_variable(const condition_variable&) = delete;   //默认构造函数无参

条件变量的wait函数:

void wait( std::unique_lock<std::mutex>& lock );//Predicate是lambda表达式。template< class Predicate >void wait( std::unique_lock<std::mutex>& lock, Predicate pred );//以上二者都被notify_one())或notify_broadcast()唤醒,但是//第二种方式是唤醒后也要满足Predicate的条件。//如果不满足条件,继续解锁互斥量,然后让线程处于阻塞或等待状态。//第二种等价于while (!pred()){    wait(lock);}

例子:

#include #include #include #include #include  std::mutex m;std::condition_variable cv;std::string data;bool ready = false;bool processed = false; void worker_thread(){    // Wait until main() sends data    std::unique_lock<std::mutex> lk(m);    //子进程的中wait函数对互斥量进行解锁,同时线程进入阻塞或者等待状态。    cv.wait(lk, []{return ready;});     // after the wait, we own the lock.    std::cout << "Worker thread is processing data\n";    data += " after processing";     // Send data back to main()    processed = true;    std::cout << "Worker thread signals data processing completed\n";     // Manual unlocking is done before notifying, to avoid waking up    // the waiting thread only to block again (see notify_one for details)    lk.unlock();    cv.notify_one();} int main(){    std::thread worker(worker_thread);     data = "Example data";    // send data to the worker thread    {        //主线程堵塞在这里,等待子线程的wait()函数释放互斥量。        std::lock_guard<std::mutex> lk(m);        ready = true;        std::cout << "main() signals data ready for processing\n";    }    cv.notify_one();     // wait for the worker    {        std::unique_lock<std::mutex> lk(m);        cv.wait(lk, []{return processed;});    }    std::cout << "Back in main(), data = " << data << '\n';     worker.join();}

在以上的代码中,子线程先对互斥量进行加锁,在main()函数中,主线程堵塞在对互斥量的加锁这里。子进程的中wait函数对互斥量进行解锁,同时线程进入阻塞或者等待状态。

通知wait()取消对线程的阻塞有:

  • notify_one()

通知第一个进入阻塞或者等待的线程。

  • notify_broadcast()

通知全部进入阻塞或者等待的线程。

spurious wakeups(虚假唤醒)

用于多线程竞争条件下,具体含义去参考官方文档。我说一下形象的意思就是你妈同时通知你爸和你去做饭,做饭只需要一个人做即可, 当你去准备做饭时,你爸已经在做饭了,所以你就相当于被虚假唤醒了。

顺便说一下Linux环境下的条件变量, 其实C++11标准也就是对condition_variable的一个封装。

以下为Linux环境下的函数:

pthread_cond_init();pthread_cond_destroy();pthread_cond_wait()pthread_cond_signal();pthread_cond_broadcast();

这些会另外写一篇文章。

0f247749ef01bbaecb1922c68fbacba2.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值