C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为。通常的做法是在修改共享数据成员的时候进行加锁--mutex。在使用锁的时候通常是在对共享数据进行修改之前进行lock操作,在写完之后再进行unlock操作,进场会出现由于疏忽导致由于lock之后在离开共享成员操作区域时忘记unlock,导致死锁。

针对以上的问题,C++11中引入了std::unique_lock与std::lock_guard两种数据结构。通过对lock和unlock进行一次薄的封装,实现自动unlock的功能。std::unique_lock 与std::lock_guard都能实现自动加锁与解锁功能,但是std::unique_lock要比std::lock_guard更灵活,但是更灵活的代价是占用空间相对更大一点且相对更慢一点。

std::condition_variable 是条件变量,更多有关条件变量的定义参考维基百科。Linux 下使用 Pthread 库中的 pthread_cond_*() 函数提供了与条件变量相关的功能, Windows 则参考 MSDN

当 std::condition_variable 对象的某个 wait 函数被调用的时候,它使用 std::unique_lock(通过 std::mutex) 来锁住当前线程。当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。

std::condition_variable 对象通常使用 std::unique_lock<std::mutex> 来等待,如果需要使用另外的 lockable 类型,可以使用 std::condition_variable_any 类,本文后面会讲到 std::condition_variable_any 的用法。

template<typename T>
class SimpleSyncQueue
{
public:
SimpleSyncQueue(){}
~SimpleSyncQueue(){}
void Put(const T& element)
{
std::lock_guard<std::mutex> locker(m_mutex);
m_queue.push_back(element);
m_NotEmpty.notify_all();
}
void Take(T& result)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_NotEmpty.wait(locker, [this](){cout << "take wait!" << endl; return !m_queue.empty(); });
result = m_queue.front();
m_queue.pop_front();
}
bool Empty()
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.empty();
}
size_t Size()
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size();
}
private:
std::list<T> m_queue;
std::mutex m_mutex;
std::condition_variable m_NotEmpty;
}; SimpleSyncQueue<int> queue;
void Thread1func()
{
for (int i = ; i < ; i++)
{
queue.Put(i);
cout << "size: "<<queue.Size() << endl;
}
}
void Thread2func()
{
int res;
for (int i = ; i < ; i++)
{
queue.Take(res);
cout << "teke res: " << res << endl;
}
}
void Test14()
{
std::future<void> future1 = std::async(std::launch::async,Thread1func);
//Sleep(1000);
std::future<void> future2 = std::async(std::launch::async, Thread2func);
future1.wait();
future2.wait();
} 某次执行结果如下:
 

基于std::mutex std::lock_guard std::condition_variable 和std::async实现的简单同步队列的更多相关文章

  1. 【C/C++开发】C++11 并发指南三(std::mutex 详解)

    本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南一(C++11 多线程初探)(本章计划 1-2 篇,已完成 1 篇) C ...

  2. C++11 并发指南三(std::mutex 详解)

    上一篇<C++11 并发指南二(std::thread 详解)>中主要讲到了 std::thread 的一些用法,并给出了两个小例子,本文将介绍 std::mutex 的用法. Mutex ...

  3. C++11并发——多线程std::mutex (二)

    https://www.cnblogs.com/haippy/p/3237213.html Mutex 又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 <mute ...

  4. C++11 并发指南三(std::mutex 详解)(转)

    转自:http://www.cnblogs.com/haippy/p/3237213.html 上一篇<C++11 并发指南二(std::thread 详解)>中主要讲到了 std::th ...

  5. 使用std::mutex取代QMutex

    为了保证对某个资源的操作是原子性的(对资源读写时,只有当前的操作结束,才允许另外线程对其操作,这里有个理解误区,资源操作原子性不是说,当前某个线程获得了某个资源使用权,然后线程执行时间完毕,要切换线程 ...

  6. C++11并发之std::mutex

    知识链接: C++11并发之std::thread   本文概要: 1. 头文件. 2.std::mutex. 3.std::recursive_mutex. 4.std::time_mutex. 5 ...

  7. C++11的mutex和lock_guard,muduo的MutexLock 与MutexLockGuard

    互斥锁是用来保护一段临界区的,它可以保证某段时间内只有一个线程在执行一段代码或者访问某个资源. C++11的mutex和lock_guard C++11新增了mutex,使用方法和linux底下的常用 ...

  8. C++11:基于std::queue和std::mutex构建一个线程安全的队列

    C++11:基于std::queue和std::mutex构建一个线程安全的队列 C++中的模板std::queue提供了一个队列容器,但这个容器并不是线程安全的,如果在多线程环境下使用队列,它是不能 ...

  9. C++11 并发之std::thread std::mutex

    https://www.cnblogs.com/whlook/p/6573659.html (https://www.cnblogs.com/lidabo/p/7852033.html) C++:线程 ...

随机推荐

  1. IE浏览器兼容性模式

    最近支持公司的一个内部业务管理系统,系统是基于jQuery来实现:用了2年的MVVM框架的我转向这个完全使用jQuery框架来开发的系统,真是相当不爽(相信用过MVVM框架的跟我是相同的感受):更为憋 ...

  2. 饭否Oauth记录

    饭否Oauth授权   首先去饭否申请一个应用,创建新应用即可,等待审核.审核通过了之后会拿到consumer_key和consumer_secret.这两个值先记录在代码里.后面经常用到. 然后第一 ...

  3. Django(ORM查询1)

    day69 参考:http://www.cnblogs.com/liwenzhou/p/8660826.html 在Python脚本中调用Django环境 orm1.py import os if _ ...

  4. EF6使用Mysql,踏过的那些坑

    在vs2013中使用mysql连接entityFramework经常会遇到这个问题:您的项目引用了最新实体框架:但是,找不到数据连接所需的与版本兼容的实体框架数据提供程序.请退出此向导,安装兼容提供程 ...

  5. Java按时间梯度实现异步回调接口

    1. 背景 在业务处理完之后,需要调用其他系统的接口,将相应的处理结果通知给对方,若是同步请求,假如调用的系统出现异常或是宕机等事件,会导致自身业务受到影响,事务会一直阻塞,数据库连接不够用等异常现象 ...

  6. postgresql-查看各个数据库大小

    查看各个数据库表大小(不包含索引),以及表数据量 mysql: select table_name,concat(round((DATA_LENGTH/1024/1024),2),'M')as siz ...

  7. ProxySQL 部署 Single Writer Failover 读写分离 (PXC)

    主机信息: Proxysql: 如果你忽略了ProxySQL会报告主机组的变化,我建议把它设置为0,除非你试图调试"某些东西",否则你的日志将很快变得巨大.UPDATE globa ...

  8. 基于alpine用dockerfile创建的nginx镜像

    1.下载alpine镜像 [root@docker43 ~]# docker pull alpine Using default tag: latest Trying to pull reposito ...

  9. 剑指offer七之斐波那契数列

    一.题目 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项.n<=39. 二.思路 序号:                  0  1   2   3  4   5  ...

  10. 把 Elasticsearch 当数据库使:聚合后排序

    使用 https://github.com/taowen/es-monitor 可以用 SQL 进行 elasticsearch 的查询.有的时候分桶聚合之后会产生很多的桶,我们只对其中部分的桶关心. ...