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 ...
随机推荐
- WPF MVVM TreeView 实现 右键选中 右键菜单
1.非MVVM模式:下载源代码WpfApplication1.zip <TreeView Height="200" PreviewMouseRightButtonDown=& ...
- 【c++习题】【17/4/16】动态分配内存
#include<iostream> #include<cstring> #define N 100 using namespace std; class String{ pu ...
- Keras实现autoencoder
Keras使我们搭建神经网络变得异常简单,之前我们使用了Sequential来搭建LSTM:keras实现LSTM. 我们要使用Keras的functional API搭建更加灵活的网络结构,比如说本 ...
- web页面如何打包封闭成手机APP
所谓的webApp就是html页面跟原生app结合而成的一种应用,这种应用的开发可以节省不少的成本,做出来的app跟原生一样,webApp利用框架技术可以让你有使用app的感觉,具体可以看平安银行的a ...
- html checkbox多选框语法与结构
<input name="Fruit" type="checkbox" value="" /> 用法用例 <foreach ...
- java-登陆界面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- ImageView显示图像控件
ImageView显示图像控件 一.简介 1. 2. ImageView,图像视图,直接继承自View类,它的主要功能是用于显示图片,实际上它不仅仅可以用来显示图片,任何Drawable对象都可以使用 ...
- python 图像库PIL详解
PIL详细文档 The most important class in the Python Imaging Library is the Image class, defined in the mo ...
- GeometryServer
http://blog.csdn.net/limina/article/details/8364515
- 51nod 1503 多线程dp
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1503 1503 猪和回文 题目来源: CodeForces 基准时间限制 ...