c++11 thread的学习
http://www.cnblogs.com/wxquare/p/6736202.html
还没开始 留个链接
使用c++11 thread支持实现 一个生产者消费者模型
下面是一个生产者消费者问题,来介绍condition_variable的用法。当线程间的共享数据发生变化的时候,可以通过condition_variable来通知其他的线程。消费者wait 直到生产者通知其状态发生改变,Condition_variable是使用方法如下: 运行过程如下!!!!!!!!!
·当持有锁之后,线程调用wait
·wait解开持有的互斥锁(mutex),阻塞本线程,并将自己加入到唤醒队列中
·当收到通知(notification),该线程从阻塞中恢复,并加入互斥锁队列(mutex queue)
.线程被唤醒之后继续持有锁运行
Condition variable有两种类型:condition_variable 和 condition_variable_any,
前一种效率更高,但是使用不够灵活,只支持std::unique_lock<std::mutex>类型的互斥锁;
后一种比较灵活,支持所有类型的锁,但是效率稍微低一些。
有一点需要注意的是使用condition variable进行通信的线程,condition variable 需要使用相同的互斥信号量(mutex)。
例子:!!!!
- #include <thread>
- #include <iostream>
- #include <mutex>
- #include <queue>
- #include <condition_variable>
- #include <atomic>
- using namespace std;
- int main()
- {
- mutex lockBuffer; //申明互斥信号量
- volatile bool ArretDemande = false; //使生产、消费过程的结束
- queue<long> buffer;
- condition_variable_any cndNotifierConsommateurs;//condition variable
- condition_variable_any cndNotifierProducteur;
- thread ThreadProducteur([&]()//生产者线程
- {
- std::atomic<long> interlock;//对interlock的操作将是原子的
- interlock=;
- while(true)
- {
- std::this_thread::sleep_for (chrono::milliseconds ());
- long element=interlock.fetch_add ();//【1】
- lockBuffer.lock ();
- while(buffer.size()== && ArretDemande ==false)
- {
- cndNotifierProducteur.wait (lockBuffer);//【2】
- }
- if (ArretDemande==true)
- {
- lockBuffer.unlock ();
- cndNotifierConsommateurs.notify_one ();//【3】
- break;
- }
- buffer.push(element);
- cout << "Production unlement :" << element << " size :" << buffer.size() << endl;
- lockBuffer.unlock ();
- cndNotifierConsommateurs.notify_one ();
- }
- } );
- thread ThreadConsommateur([&]()
- {
- while(true)
- {
- lockBuffer.lock ();
- while(buffer.empty () && ArretDemande==false)
- {
- cndNotifierConsommateurs.wait(lockBuffer);
- }
- if (ArretDemande==true && buffer.empty ())
- {
- lockBuffer.unlock();
- cndNotifierProducteur.notify_one ();
- break;
- }
- long element=buffer.front();
- buffer.pop ();
- cout << "Consommation element :" << element << " size :" << buffer.size() << endl;
- lockBuffer.unlock ();
- cndNotifierProducteur.notify_one ();
- }
- } );
- std::cout << "Pour arreter pressez [ENTREZ]" << std::endl;
- getchar();
- std::cout << "Arret demande" << endl
- ArretDemande=true;
- ThreadProducteur.join();
- ThreadConsommateur.join();
- cout<<"Main Thread"<<endl;
- return ;
- }
运行结果:
- 这个 不是我的 linux下的运行样子 我运行的结果类似这样 意思相同!!!!!!!
对程序进行一下说明,程序中有三个线程,主线程、生产者线程、消费者线程,三个线程之间乱序执行,通过一些全局变量来控制他们的执行顺序。
主线程的作用是控制生产消费过程是否结束,当程序运行之后,主线程通过getchar()接收一个输入,接收到输入后会将ArretDemande设置为true,另外两个线程会终止。
生产者线程将生产出来的数据放在一个queue类型的buffer中,并解锁,通知消费之线程,buffer中最多“能”存10个数据,如果buffer中已经有10个数据还没有被取走,则会通知消费者线程“消费”,如果ArretDmande被置位,则打开锁,并通知消费之线程。消费者线程主要是将buffer中的数据取出来,当buffer为空的时候阻塞自己,并通知生产者线程,当ArretDemande被置位,且已经消费完产品则解锁,并通知生产者线程。需要注意的是需要通信的生产者和消费者这两个线程通过condition variable来实现通信,必须操作同一个mutex,这里是lockbuffer,并且每次Notify都会打开当前锁。
程序中对interlock进行的操作是原子的,interlock.fet_add(N),效果是将interlock加N,然后返回interlock在加N之前的值,atomic类型是通过一定的内存顺序规则来实现这个过程的。
虽然conditon_variable 只能支持std::unique_lock<std::mutex>类型的互斥锁,但是在大部分情况下已经够用,而且使用std::unique_lock<std::mutex>会比较简单,因为std::unique_lock<std::mutex>在声明的时候就会初始化,在生命周期结束之后就会自动解锁,因此我们不用太花精力来考虑什么时候解锁。
例子!!!!!!!!!
- #include <condition_variable>
- #include <mutex>
- #include <thread>
- #include <iostream>
- #include <queue>
- #include <chrono>
- int main()
- {
- std::queue<int> produced_nums;
- std::mutex m;;
- std::condition_variable cond_var;
- bool done = false;
- bool notified = false;//这个变量在每一个线程中 是每个线程所独有的
- std::thread producer([&]() {
- for ( int i = ; i < ; ++i) {
- std::this_thread::sleep_for(std::chrono:: seconds());
- std:: unique_lock<std::mutex > lock(m); //May lock mutex after construction, unlock before destruction.
- std::cout << "producing " << i << '\n' ;
std::cout<<notified<<'\n';//自己 添加的线程的局部变量检测 参数 验证局部变量线程独享!!!!!- produced_nums.push(i);
- notified = true;
std::cout<<notified<<'\n';//同上- cond_var.notify_one();
- }
- done = true; //运行到这里 生产其实已经结束了
- cond_var.notify_one();// 防止消费者卡死 唤醒最后一个消费者结束 这步需要注意!!!!!!!! 有时候 运行会卡住
- });
- //cond_var.notify_one();
- std::thread consumer([&]() {
- while (!done) {
- std:: unique_lock<std::mutex > lock(m);
- while (!notified) { // loop to avoid spurious wakeups 就是说生产者已经生产了 现在队列有任务 不为空 可以去消费了 不需要挂起了!!!!!!!
- cond_var.wait(lock);
- }
- while (!produced_nums.empty()) { //当队列不为空 开始消费了
- std::cout << "consuming " << produced_nums.front() << '\n';
- produced_nums.pop();
- }
- notified = false;
- }
- });
- producer.join();
- consumer.join();
- return ;
- }
- 运行结果:
producing 0
consuming 0
producing 1
consuming 1
producing 2
consuming 2
producing 3
consuming 3
producing 4
consuming 4
以上两个例子 验证了c++11的不同的条件变量 对应的不同的锁 其中有一个锁 无需释放 对应的条件变量 则 不同!!!!!!
来一个教科书的 线程解决生产者消费者问题的demo
- #include<stdio.h>
- #include<pthread.h>
- #include<unistd.h>
- #define MAX 10000000 //需要生产的数量
- pthread_mutex_t the_mutex; //全局锁
- pthread_cond_t condc, condp;//全局条件变量
- int buffer = ; //全局共享变量
- void *producer(void*ptr){//生产数据
- int i;
- for(i=;i<=MAX;i++){
- pthread_mutex_lock(&the_mutex);//互斥使用 缓冲区buffer
- while(buffer !=)pthread_cond_wait(&condp,&the_mutex);
- buffer=i; //将数据放入缓冲区
- printf("Is producering %d\n",buffer);
- pthread_cond_signal(&condc);//唤醒消费者
- pthread_mutex_unlock(&the_mutex);//释放锁 就是释放了缓冲区buffer
- }
- pthread_exit();//over 线程
- }
- void *consumer(void *ptr){//消费数据
- int i;
- for(i=;i<=MAX;i++){
- sleep();
- pthread_mutex_lock(&the_mutex);//互斥使用缓冲区
- printf("Is consumering \n");
- while(buffer==)pthread_cond_wait(&condc,&the_mutex);
- buffer = ; //从缓冲区取出数据
- pthread_cond_signal(&condp);//唤醒生产者
- pthread_mutex_unlock(&the_mutex);////释放锁 就是释放了缓冲区buffer
- }
- pthread_exit();//over 线程
- }
- int main(int argc,char**argv)
- {
- pthread_t pro,con;
- pthread_mutex_init(&the_mutex,);
- pthread_cond_init(&condc,);
- pthread_cond_init(&condp,);
- pthread_create(&con,,consumer,);
- pthread_create(&pro,,producer,);
- pthread_join(pro,);//回收线程资源
- pthread_join(con,);
- pthread_cond_destroy(&condc);//销毁条件变量
- pthread_cond_destroy(&condp);
- pthread_mutex_destroy(&the_mutex);//销毁锁
- return ;
- }
已经进过测试 Linux Ok!!!!!!!!!!!!!!
就先到这里吧!!!
c++11 thread的学习的更多相关文章
- 漫谈C++11 Thread库之原子操作
我在之前一篇博文<漫谈C++11 Thread库之使写多线程程序>中,着重介绍了<thread>头文件中的std::thread类以及其上的一些基本操作,至此我们动手写多线程程 ...
- java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍
线程的概述: 线程是程序的多个执行路径,执行调度的单位,依托于进程存在.线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系 ...
- HTML5初学者福利!11个在线学习网站推荐
HTML5初学者福利!11个在线学习网站推荐 HTML5的强大及流行趋势,让更多的人想要系统的对它进行学习.而大多数人获取HTML5知识的重要途径都是网络,不过面对五花八门的搜索结果,是不是觉得摸不着 ...
- DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)
本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com 注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...
- DirectX 11游戏编程学习笔记之6: 第5章The Rendering Pipeline(渲染管线)
本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com 注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...
- C++11 Thread多线程的学习心得与问题
C++11 ,封装了thread的多线程的类,这样对多线程的使用更加方便. 多线程的原理我不加赘述,可以参看操作系统等参考书. 多线程代码可以最大化利用计算机性能资源,提高代码的运行效率,是常用优化方 ...
- c++11: <thread>学习
<thread>头文件中包含thread类与this_thread命名空间,下面逐一介绍. thread类 1. 构造函数 (1)默认构造函数 thread() noexcept; 默认构 ...
- 漫谈c++11 Thread库之使写多线程程序
c++11中最重要的特性之一就是对多线程的支持了,然而<c++ primer>5th却没有这部分内容的介绍,着实人有点遗憾.在网上了解到了一些关于thread库的内容.这是几个比较不错的学 ...
- c++11 线程池学习笔记 (一) 任务队列
学习内容来自一下地址 http://www.cnblogs.com/qicosmos/p/4772486.html github https://github.com/qicosmos/cosmos ...
随机推荐
- 连接并同步windows下的git仓库
1. 需求 电脑A和电脑B本来通过服务器同步工作目录.服务器时linux系统上有个裸仓库,不管在A上还是B上工作,工作完毕后使用git go与服务器仓库同步.A和B都是windows系统,在工作目录下 ...
- python基础-正则2
正则函数 Python提供re模块,包含所有正则表达式的功能 由于python的字符串本身也有\转义,所以需要注意: s = "ABC\\-001" 对应的正则表达式应为:'ABC ...
- resEdit
resEdit:一个图形界面编辑工具,它不但可以用来编写程序所图形界面(如修改图标.菜单.鼠标.版本信息等),还支持了对exe.dll等执行文件内的资源(图标.菜单.鼠标指针.位图.版本信息)等进行修 ...
- zero to one (3)
工具使用 AWVS Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的Web网络漏洞扫描工具,它通过网络爬虫测试你的网站安全,检测流行安全漏洞. 功能及特 ...
- ACM学习历程——POJ 2376 Cleaning Shifts(贪心)
Description Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cleaning ...
- SQL 优化总结(三) SQL子句
SQL子句 尽可能编写优化器可以优化的语句. 1. SELECT子句 (1) 在查询Select语句中用Where字句限制返回的行数,避免表扫描,如果返回不必要的数据,浪费了服务器的I/O资源,加重了 ...
- 物联网项目开发必读 深度分析MQTT协议优缺点
物联网并不仅仅是一种网络,而是一个新的生态环境,它描述的本质是越来越多的使用物品通过网络连接在一起并可使用单个或者多个的终端设备对它们进行各种控制和使用—当然,工业上的物联网通常连接到的石鼓传感器或者 ...
- [spoj694&spoj705]New Distinct Substrings(后缀数组)
题意:求字符串中不同子串的个数. 解题关键:每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数. 1.总数减去height数组的和即可. 注意这里height中为什么不需 ...
- 设置Mvc路由Asp.net 与 mvc同用
App_start/RouteConfig.cs/RegisterRoutes(RouteConllection routes) { routes.IgnoreRoute("{resourc ...
- IntelliJ IDEA 中使用region代码折叠
我使用的版本为2018.3,如下图: 选中要折叠的代码,使用快捷键:Ctrl+Alt+T,打开Surround With菜单,点击region...endregion Comments项(红框),如下 ...