漫话C++0x(五)—- thread, mutex, condition_variable
熟悉C++98的朋友,应该都知道,在C++98中没有thread, mutex, condition_variable这些与concurrency相关的特性支持,如果需要写多线程相关程序,都要借助于不同平台上各自提供的api,这样带来的问题就是程序的跨平台移植性比较差,经常要用一大堆的#ifdef WIN32类似的宏来区分不同的平台,搞得程序很难看。C++0x最原始的初衷之一就是为了让C++的功能更加强大,更加方便使用。现如今硬件如此发达,concurrency在程序设计中已经是司空见惯的事情了,如果C++再不支持这些concurrency相关的特性,就真的out了。现在,C++程序员的福音到了,C++0x提供了对thread, mutex, condition_variable这些concurrency相关特性的支持,以后多线程这一块的代码可以完全跨平台了,而且由于C++0x封装的都比较好,代码写起来也十分简洁。下面开始介绍今天的内容。
- 1. thread
写过多线程程序的朋友,相信对thread本身都不会陌生,这里不对thread本身做太多的说明,以介绍C++0x中提供的thread的用法为主。请大家先看下面的例子:
1 |
#include < iostream> |
下面我们来通过分析上面的例子,来说明一下thread的用法。上面的t1-t4的四个例子,分别是thread的四种构造方式,我们一一来介绍一下:
- (1)这种方式是通过变参数模板实现的,第一个参数是线程入口函数的地址,后面的参数按函数调用时的参数顺序传入。这里需要说明两点:一是变参模板也是C++0x新增的特性,将会在后面的文章中介绍;二是,类成员函数的第一个参数永远是this,所以这里第一个参数放的是对象本身。
- (2)这种方式是传入一个std::function对象,bind/function在前一篇中有介绍,不熟悉的朋友可以先看一下C++0x系列的第四篇。
- (3)这种方式是传入一个lambda表达式,也即一个closure,是比较常用的方式。关于lambda也在上一篇中有介绍。
- (4)这种方式是最简单,最常用的方式,直接传入一个函数,写过多线程程序的朋友应该对这种方式最为熟悉。
上面介绍了C++0x thread的基本用法,下面需要再补充几点使用过程需要注意的事项:
- (1)如果入口函数的参数是以引用或指针形式传入的,需要使用者保证在线程运行过程中,这些参数一直是有效的。同时,如果有多个线程会访问或者修改这些变量,需要使用者做好同步,保证一致性。
- (2)关于上面提到的几种构造方式,简单的直接用4,复杂的推荐的选择顺序:1->3->2,即变参模板方式->lambda方式->bind方式
- (3)通常需要等子线程运行完,主线程才退出,所以在主线程中通常需要调各子线程的join()。
- 2. mutex
mutex实现的是“互斥锁”的语义,在多线程的程序中,经常需要通过锁的机制来保证数据的一致性,C++0x提供了下面四种语义的mutex:
- (1) std::mutex: 普通的互斥锁,不能递归使用
- (2) std::timed_mutex:带超时的互斥锁,不能递归使用
- (3) std::recursive_mutex:递归互斥锁
- (3) std::recursive_timed_mutex:带超时的递归互斥锁
关于mutex的使用,我们通常建议使用RAII(Resource Acquisition is Initialization)的方式,即在构造的时候lock, 析构的时候unlock, 不建议直接显式的lock/unlock,因为这样比较容易出错。因此,C++0x也提供了两个工具类std::lock_guard和std::unique_lock来辅助我们使用mutex,下面我们通过例子来看一下具体的使用:
1 |
#include < mutex> |
从上面的例子,相信大家可以对mutex的基本使用方法都应该比较清楚了,由于mutex本身就比较简单,这里不再赘言。说一下std::unique_lock和std::lock_guard的区别,std::lock_guard只允许RAII方式的使用,而std::unique_lock可以在构造之后调用lock/unlock, 更加灵活一些,但使用的时候出错的机率也更大一些,所以如果没有什么特殊的需求,通常推荐尽量使用std::lock_guard.
- 3. condition_variable
关于condition_variable,它的语义是今天讲的三个内容里面相对复杂一些的,我在之前也写过一篇关于它的文章,不熟悉的朋友可以先阅读一下《条件变量(Condition Variable)详解》这篇文章,先了解一下条件变量,以方便理解后面的内容。我们知道,条件变量主要是用在多线程之间修改了shared_data之后的相互通信,由于条件变量在多线程编程中非常有用,所以C++0x也添加了对条件变量的支持,下面是C++0x提供的两种不同类型的条件变量:
- (1)condition_variable: 用在std::unique_lock< std::mutex>上wait, 比较高效。
- (2)condition_variable_any: 可以用在任意mutex上wait, 比较灵活,但效率比condition_variable差一些。
下面我们通过例子来看看,条件变量在C++0x中的使用方式:
1 |
// global |
上面的例子,基本覆盖了C++0x提供的条件变量的主要用法。下面我们来一一分析一下,帮助大家更好的理解:
- (1)关于wait,有三种基本的用法:第1种是在指定的条件上循环等待,直到条件为真notify时才会继续执行后面的逻辑;第2种用法语义上和第1种是一样的,但是不是用户做显式的loop等待,用户传入一个需要满足的条件的closure, wait一直等到这个条件为真被notify时才会返回继续执行下面的逻辑,可以理解为这时候,在wait内部有一个loop;第3 种用法,加了一个超时的语义,wait一直等到条件为真或者超时,被notify时才会返回继续执行下面的逻辑。
- (2)关于notify, 有两种:第1种是notify_one, 只唤醒一个在wait的线程; 第2种是notify_all,唤醒所有在wait的线程,相当于一个broadcast的语义。
以上即是今天的主要内容,希望对正在学习C++0x的朋友有所帮助,荣幸之至!
漫话C++0x(五)—- thread, mutex, condition_variable的更多相关文章
- 【转帖】漫话C++0x(四) —- function, bind和lambda
实在是觉得此文总是去翻感觉不太好.于是果断转过来了,想看原文的请戳:http://www.wuzesheng.com/?p=2032 本文是C++0x系列的第四篇,主要是内容是C++0x中新增的lam ...
- pthread thread mutex synchronous asynchronous communication
设置进程绑定状态的函数pthread_attr_setscopepthread_attr_t 指向属性结构的指针第二个参数 绑定类型 pthread_scope_system()pthread_sco ...
- C++11之thread线程
今天由于项目需求(其实是某门课的一个大作业,不好意思说出口啊...),想要使用多线程.相信大家一般用的是linux上的POSIX C或windows上的线程库,然而这些线程库以来于特定系统,并不“标准 ...
- C++11并发——多线程std::thread (一)
https://www.cnblogs.com/haippy/p/3284540.html 与 C++11 多线程相关的头文件 C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是< ...
- C++11 并发指南一(C++11 多线程初探)
引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...
- C++11 并发指南一(C++11 多线程初探)(转)
引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...
- 【C/C++开发】C++11 并发指南一(C++11 多线程初探)
引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...
- 【转】C++ 11 并发指南一(C++ 11 多线程初探)
引言 C++ 11自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些C++ 11的新特性,算是记录一下自己学到的东西吧,和大家共勉. 相信Linux程序员都用过Pthrea ...
- 【C++】c++11多线程初探
相关头文件c++11 新标准中引入了四个头文件来支持多线程编程,他们分别是<atomic> ,<thread>,<mutex>,<condition_vari ...
随机推荐
- .NET微信支付(H5仅限公众号支付)
闲来无事,恰好有一个要用微信公众平台支付的功能,研究来研究去,就是要细心和多看腾讯提供的文档.当然有几个坑是很有必要说明一下的 公众号支付,这里统一叫H5支付,以下都是. 在做H5支付的时候,第一步就 ...
- sqlserver之二进制和字符串sql语句
正常情况下我们对数据库的操作就是如下的写法来操作数据库 ID AS 编号,BookName AS 书名 FROM dbo.books ORDER BY ID; ; 但是在客户正在使用的数据库里,我们开 ...
- centos5.6部署gcc4.7编译的程序导致问题
因为用了c++0x的一些新特性,必须使用4.6及以上的版本编译,所以使用了4.7编译,运行时提示错误 libstdc++.so.6(GLIBCXX_3.4.14) 错误 这个时候下了个glibc2.7 ...
- Touch ID指纹解锁使用
Touch ID是iPhone5S后加入的一项新的功能,也就是大家熟知的指纹识别技术.大家用得最多的可能是手机的解屏操作,不用在和以前一样输入手机的四位数密码进行验证.一方面不用担心密码被别人看到,另 ...
- Delegate&Event
Delegate 1.基本类: public class Student { public int Id { get; set; } public string Name { get; set; } ...
- office2013发布博客
0, 喜欢用world记笔记,并查上一些配图.但是再想重新发到博客上,图片不得不重新上传十分蛋疼. world直接发布博客功能太棒了,直接绑定账号和url就可以发送了,爽YY!!! 1,新建一个博客文 ...
- COM原理
1, 进程内组件:服务程序杯加载到客户的进程空间,通常是DLL的形式.本地组件:服务程序与与客户程序在同一台电脑上,通常是EXE.远程组件: 服务程序与与客户程序在不同的电脑上,可以是DLL模块也可是 ...
- 在使用masm32 rc编译资源文件.rc出现的问题
fatal error RC1004: unexpected end of file found 很蛋疼.然来是.h宏定义文件中.最后一行加个回车键即可.否则就提示这错误.
- input获取永久焦点
$(function () { $('#test').blur(function () { var that = this; //或者用闭包 setTimeout(function () { $(th ...
- ARC forbids explicit message send of release
http://blog.sina.com.cn/s/blog_7b9d64af01019rqt.html