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的学习的更多相关文章

  1. 漫谈C++11 Thread库之原子操作

    我在之前一篇博文<漫谈C++11 Thread库之使写多线程程序>中,着重介绍了<thread>头文件中的std::thread类以及其上的一些基本操作,至此我们动手写多线程程 ...

  2. java基础知识回顾之java Thread类学习(十)--线程的状态以及转化使用的方法介绍

       线程的概述:         线程是程序的多个执行路径,执行调度的单位,依托于进程存在.线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间叫做线程栈,是建立线程的时候由系 ...

  3. HTML5初学者福利!11个在线学习网站推荐

    HTML5初学者福利!11个在线学习网站推荐 HTML5的强大及流行趋势,让更多的人想要系统的对它进行学习.而大多数人获取HTML5知识的重要途径都是网络,不过面对五花八门的搜索结果,是不是觉得摸不着 ...

  4. DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)

            本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com         注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...

  5. DirectX 11游戏编程学习笔记之6: 第5章The Rendering Pipeline(渲染管线)

            本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com         注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...

  6. C++11 Thread多线程的学习心得与问题

    C++11 ,封装了thread的多线程的类,这样对多线程的使用更加方便. 多线程的原理我不加赘述,可以参看操作系统等参考书. 多线程代码可以最大化利用计算机性能资源,提高代码的运行效率,是常用优化方 ...

  7. c++11: <thread>学习

    <thread>头文件中包含thread类与this_thread命名空间,下面逐一介绍. thread类 1. 构造函数 (1)默认构造函数 thread() noexcept; 默认构 ...

  8. 漫谈c++11 Thread库之使写多线程程序

    c++11中最重要的特性之一就是对多线程的支持了,然而<c++ primer>5th却没有这部分内容的介绍,着实人有点遗憾.在网上了解到了一些关于thread库的内容.这是几个比较不错的学 ...

  9. c++11 线程池学习笔记 (一) 任务队列

    学习内容来自一下地址 http://www.cnblogs.com/qicosmos/p/4772486.html github https://github.com/qicosmos/cosmos ...

随机推荐

  1. centos7在VMware下配置网络连接

    安装成功以后,首先更改vmwar的虚拟网络设置 1.参考连接:http://www.cnblogs.com/liongis/p/3265458.html 2.然后将虚拟机的设置里面将网络配置的连接方式 ...

  2. 常见css兼容问题

    链接的虚线框问题 <!-- html --> <a class="noDashedBox" href="#"><img src=& ...

  3. 【Shell】Linux 一行 多命令

    http://www.cnblogs.com/koreaseal/archive/2012/05/28/2522178.html 要实现在一行执行多条Linux命令,分三种情况: 1.&&am ...

  4. Codeforces Round #394 (Div. 2) 题解

    无需吟唱,直接传送 problem A 题目大意 已知有n个偶数,m个奇数,问这些数有没有可能组成一个严格递增1的序列 题解 判断abs(n,m) <= 1即可,注意n,m均为0的情况. Cod ...

  5. 【Lintcode】046.Majority Number

    题目: Given an array of integers, the majority number is the number that occurs more than half of the ...

  6. 规划ASM DISK GROUP、查看asm 磁盘当前状态、mount or dismount 磁盘组、检查磁盘组 metadata 的内部一致性

    规划ASM DISK GROUP: 1. 每个磁盘组里的磁盘应该大小.性能.新旧等一致,不能有太大差距 2. 对database files 和 fast recovery area 分别创建不同的d ...

  7. BZOJ3127:[USACO2013OPEN]Yin and Yang

    浅谈树分治:https://www.cnblogs.com/AKMer/p/10014803.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem. ...

  8. hdu 1521 排列组合 —— 指数型生成函数

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1521 标准的指数型生成函数: WA了好几遍,原来是多组数据啊囧: 注意精度,直接强制转换(int)是舍去小 ...

  9. bzoj1042硬币购物——递推+容斥

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1042 递推,再用容斥原理减掉多余的,加上多减的……(dfs)即可. 代码如下: #includ ...

  10. Getting Started with OpenMP

    Getting Started with OpenMP* Abstract As you probably know by now, to get the maximum performance be ...