C++11新特性之线程操作
C++11之前没有对并发编程提供语言级别的支持,这使得我们在编写可移植的并发程序时,存在诸多的不便。现在C++11增加了线程以及线程相关的类,很方便地支持了并发编程,使得编写的多线程程序的可移植性得到了很大的提高。
1. 线程
1.1 线程的创建
#inclde <thread>
std::thead t(ThreadFun, parm1, parm2,...);
t.join();或t.detach();
join会阻塞线程,直到线程函数结束
detach让线程和线程对象分离,让线程作为后台线程去执行,但需要注意,detach之后就无法再和线程发生联系了,等于说失去了对线程的控制权。
2. 互斥量
C++11提供了以下4中语义的互斥量:
std::mutex:独占互斥量,不能递归使用
std::timed_mutex:带超时的独占互斥量,不能递归使用
std::recursive_mutex:递归互斥量,不带超时功能
std::recursive_timed_mutex:带超时的递归互斥量
2.1 独占互斥量
std::mutex m_mutex;
mutex.lock();
do something;
mutex.unlock();
注意:使用std::lock_guard<mutex> locker(m_mutex);可以简化lock/unlock的写法,同时也更安全,因为lock_guard在构造的时候会自动锁定互斥量,而在退出作用域后进行析构时就会自动解锁,从而保证了互斥量的正确操作。
try_lock()尝试锁定互斥量,如果成功则返回true
2.2 递归的独占互斥量
需要注意的是尽量不要使用递归锁:
(1)需要用到递归锁的多线程互斥处理本身就应该可以简化的,运行递归互斥很容易放纵复杂逻辑的产生
(2)递归锁比起非递归锁要麻烦,效率低
(3)递归锁虽然允许同一个线程多次获得同一个互斥量,可重复获得的最大次数并未具体说明,一旦超过一定次数会抛出std::system错误
2.3 带超时的互斥量和递归带超时的互斥量
std::timed_mutex比std::mutex多了两个超时获取锁的接口,try_lock_for和try_lock_until,这两个接口是用开设置获取互斥量的超时时间,使用时可以用一个while循环去不断地获取互斥量。
std::timed_mutex mutex;
std::chrono::secord timeout(2);
if (mutex.try_lock_for(timeout))
cout << "do work with the mutex" << endl;
else:
cout << "do work without the mutex" << endl;
3. 条件变量
3.1 说明
条件变量用于线程的同步机制,它能阻塞一个或多个线程,直到收到另外一个线程发出的同质或者超时,才会唤醒当前阻塞的线程。条件变量需要和互斥变量结合起来用。
C++提供了两种条件变量:
(1)condition_variable,配合std::unique_lock<std::mutex>进行wait操作
(2)condition_variable_any,和任意带有lock,unlock语义的mutex搭配使用,比较灵活,但效率比condition_variable低
注意以下函数的使用:
(1)std::lock_guard,它利用了RAII机制可以保证mutex的安全释放
(2)std::unique_lock与lock_guard的区别在与,前者可以自由地释放mutex,而后者需要等到std::lock_guard变量生命周期结束时才能释放。
3.2 示例实现消息循环队列
3.2.1 实现代码
// 使用C++11的新特性实现线程安全的循环消息队列
#pragma once #include<iostream>
#include<mutex>
#include<condition_variable>
using namespace std; #define MAXQUEUELEN 32
template<typename T>
class CMsgQueue
{
public:
CMsgQueue()
{
m_pQueue = new T[MAXQUEUELEN];
m_nHead = m_nTail = ;
}
~CMsgQueue()
{
Clear();
} void Push(T msg)
{
unique_lock<mutex> lock(m_Mutex);
while (IsFull())
{
cout << "消息队列已经满,请等待..." << endl;
m_ConditionVar.wait(lock);
}
cout << "Push: " << msg << endl;
m_pQueue[m_nTail] = msg;
m_nTail = m_nTail % MAXQUEUELEN + ;
m_ConditionVar.notify_all();
} bool IsFull()
{
return (m_nTail + ) % MAXQUEUELEN == m_nHead;
}
bool IsEmpty()
{
return m_nTail == m_nHead;
}
T Pop()
{
unique_lock<mutex> lock(m_Mutex);
while (IsEmpty())
{
cout << "消息队列为空,请等待..." << endl;
m_ConditionVar.wait(lock);
}
T msg = m_pQueue[m_nHead];
cout << "Pop: " << msg << endl;
m_nHead = m_nHead % MAXQUEUELEN + ;
m_ConditionVar.notify_all();
return msg;
}
void Clear()
{
if (m_pQueue != NULL)
{
delete[] m_pQueue;
m_pQueue = NULL;
}
} private:
T *m_pQueue;
int m_nHead;
int m_nTail; mutex m_Mutex;
condition_variable m_ConditionVar;
};
3.2.2 测试
void fun1(CMsgQueue<int> *pQueue)
{
for (int i = ; i < ; i++)
{
//this_thread::sleep_for(chrono::seconds(2));
pQueue->Push(i);
}
} void fun2(CMsgQueue<int> *pQueue)
{
for (int i = ; i < ; i++)
{
this_thread::sleep_for(chrono::seconds(2));
pQueue->Pop();
}
} void main()
{
CMsgQueue<int> *pQueue = new CMsgQueue<int>;
thread t1(fun1, pQueue);
thread t2(fun2, pQueue); t1.join();
t2.join(); return;
}

C++11新特性之线程操作的更多相关文章
- c++ 11 线程池---完全使用c++ 11新特性
前言: 目前网上的c++线程池资源多是使用老版本或者使用系统接口实现,使用c++ 11新特性的不多,最近研究了一下,实现一个简单版本,可实现任意任意参数函数的调用以及获得返回值. 0 前置知识 首先介 ...
- [转载] C++11新特性
C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...
- 转:c++ 11 新特性
声 明:本文源自 Danny Kalev 在 2011 年 6 月 21 日发表的<The Biggest Changes in C++11(and Why You Should Care)&g ...
- c++学习书籍推荐《深入理解C++11 C++11新特性解析与应用》下载
百度云及其他网盘下载地址:点我 编辑推荐 <深入理解C++11:C++11新特性解析与应用>编辑推荐:C++标准委员会成员和IBM XL编译器中国开发团队共同撰写,权威性毋庸置疑.系统.深 ...
- C++11新特性总结 (二)
1. 范围for语句 C++11 引入了一种更为简单的for语句,这种for语句可以很方便的遍历容器或其他序列的所有元素 vector<int> vec = {1,2,3,4,5,6}; ...
- C++11新特性总结 (一)
1. 概述 最近在看C++ Primer5 刚好看到一半,总结一下C++11里面确实加了很多新东西,如果没有任何了解,别说自己写了,看别人写的代码估计都会有些吃力.C++ Primer5是学习C++1 ...
- 在C++98基础上学习C++11新特性
自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...
- C++11新特性——range for
很多编程语言都有range for语法功能,自C++11起,终于将这个重要功能加入C++标准中.range for语句,可以方便的遍历给定序列中的每个元素并对其执行某种操作. 1.基本语法 for(d ...
- JDK新特性关于流操作部分
// array 工具类 可以用来快捷的将数组转化为list List<String> strings = Arrays.asList("zhongguo", &quo ...
随机推荐
- 在线修改GTID模式
在线修改GTID模式 1. 在每一台机器上执行命令 SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN; 这是很重要的一步,必须确保服务器上没有违反GTID规范的 ...
- CSS3圆盘时钟
在线演示 本地下载
- 20162305李昱兴 2016-2017-2 《Java程序设计》第2周学习总结
20162305 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 教材的第二章以数据和表达式为主.在第二章的学习中,我了解了print以及println的用法 ...
- Oracle数据库使用总结
--1.使用月份作为条件筛选(to_char函数与extract函数使用) select * from test_date where to_char(dqsj,'mm') like '%07%'; ...
- gradle-rn-app工程运行须知
singwhatiwanna edited this page 16 days ago · 5 revisions Pages 7 Home Demo 工程运行须知 VirtualAPK API 概 ...
- java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]]
1.问题描述: 对于创建的springboot项目,通过启动类启动,访问没问题,但打成war部署到tomcat上启动报错,如下: 严重: ContainerBase.addChild: start: ...
- mysql-8.0.11-winx64.zip安装教程
mysql-8.0.11-winx64.zip安装教程 下载zip安装包: MySQL8.0 For Windows zip包下载地址:https://dev.mysql.com/download ...
- 远程桌面.【转】Win10 家庭(home)版启用远程桌面(Remote Desktop)功能
ZC:YeJun的台式机是 Win10家庭版,默认我们想连上她的电脑是连不上的,用下面的方式,我的笔记本可以连上了 ZC:我的下载资料,存放于 "E:\BaiduYunDownload\Wi ...
- Gulp实例(包括环境搭建的自动检测)
# Gulp实例(包括环境搭建的自动检测) Gulp是一个自动化构建工具,开发者可以使用它在项目开发过程中自动执行常见任务.下面我将完成如下的功能点并且附上源码: CSS文件打包 less文件打包 s ...
- iOS CoreData (二) 版本升级和数据库迁移
前言:最近ChinaDaily项目需要迭代一个新版本,在这个版本中CoreData数据库模型上有新增表.实体字段的增加,那么在用户覆盖安装程序时就必须要进行CoreData数据库的版本升级和旧数据迁移 ...