IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> [C++] C++11 条件变量 -> 正文阅读

[C++知识库][C++] C++11 条件变量

条件变量

C++11 提供了条件变量condition variable用于实现线程间的同步操作,需要包含头文件#include <condition_variable>,并且一般都是与互斥量mutex配合使用。

条件变量的工作方式为:

  • 使用条件变量的线程首先对互斥量加锁
  • 检查某个条件,如果条件不满足,则释放互斥锁量,进入休眠;如果条件满足,则继续执行资源操作,执行完操作后释放互斥量
  • 另外一个线程加锁执行资源操作,使条件满足后,释放互斥量,唤醒等待的线程

具体参考:std::condition_variable

成员函数

  • wait ——等待某个条件满足时,重新获取互斥量加锁并继续执行;否则释放互斥量并休眠,直至重新被唤醒再重新判断一次。互斥量必须使用unique_lock对象。
    包含两个原型
void wait(unique_lock<mutex>& __lock)	// 1
template<typename _Predicate>
void wait(unique_lock<mutex>& __lock, _Predicate __p)	// 2

_Predicate 对象是一个判断条件是否满足的函数。1)如果调用的原型没有该参数,那么第一次调用 wait 时默认条件不成立,然后进入休眠,直至其他线程唤醒它,随后进行常规的互斥量加锁操作:获取不到锁则休眠直至重新获取到锁。2)如果调用的原型有该参数,wait 会调用该函数判断返回结果是否为 true :是,则继续执行;否,则释放互斥量并阻塞休眠,直到其他线程唤醒它,此时如果条件还不满足,则线程继续休眠等待,直到有一次唤醒后条件满足了,那么它就从新对互斥量加锁并继续执行后面的操作。

  • wait_for ——在 wait 的基础上增加了一个超时时间参数,用法类似于 mutex 的 try_lock_for()
  • wait_until ——类似于mutex 的 try_lock_until()
  • notify_one ——前面提到调用wait的线程需要其他线程唤醒,那么自然就会想到如何唤醒。notify_one 唤醒多个调用 wait 后正在休眠的线程中的一个
  • notify_all ——唤醒正在休眠等待的所有线程,但它们中只有一个能够获得互斥量!

代码示例

下面的示例使用条件变量实现一个同步队列。

定义类

template<typename T>
class SyncQueue
{
public:
    SyncQueue() {}
    ~SyncQueue() {}

    void Put(const T & one)
    {
        unique_lock<mutex> locker(_mutex);
        _queue.emplace_back(one);
        _notEmpty.notify_one();
    }

    T & Take()
    {
        unique_lock<mutex> locker(_mutex);
        _notEmpty.wait(locker, [this](){ return !_queue.empty(); });

        T& one = _queue.front();
        _queue.pop_front();

        return one;
    }

    bool isEmpty()
    {
        unique_lock<mutex> locker(_mutex);

        return _queue.empty();
    }

    size_t Size()
    {
        unique_lock<mutex> locker(_mutex);

        return _queue.size();
    }

private:
    list<T> _queue;
    mutex _mutex;
    condition_variable _notEmpty;
};

测试例程

#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <list>
using namespace std;

SyncQueue<int> sq;
void PutData()
{
    for(int i = 0; i < 20; i++)
    {
        sq.Put(i);
        cout << "# sq put " << i << endl;
    }
}

void TakeData()
{
    for(int i = 0; i < 20; i++)
    {
        int one = sq.Take();
        cout << "# sq take " << one << endl;
    }
}

int main()
{
    thread t1(PutData);
    thread t2(TakeData);

    t1.join();
    t2.join();
    
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-28 12:13:13  更:2021-10-28 12:15:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:44:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码