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. IDT 信息设计工具使用

    IDT 大多使用于接外系统数据,也就是非SAP 系统数据库.虽然SAP BW 里有数仓概念,接外部系统的视图.集中在使用建模,query ,再通过BO来展示.可是有些我们需要直连数据库,取一两张表相对 ...

  2. spring框架IOC原理分析代码

    模拟ClasspathXmlApplication: package junit.test; import java.beans.Introspector; import java.beans.Pro ...

  3. L97

    We are young. So let's set the world on fire. We can burn brighter than the sun.我们是青年,让我们点亮世界,释放生命,胜 ...

  4. codeforces 569C C. Primes or Palindromes?(素数筛+dp)

    题目链接: C. Primes or Palindromes? time limit per test 3 seconds memory limit per test 256 megabytes in ...

  5. ACM学习历程——HDU4472 Count(数学递推) (12年长春区域赛)

    Description Prof. Tigris is the head of an archaeological team who is currently in charge of an exca ...

  6. Godot-3D教程-02.3D性能和局限性

    介绍 Introduction Godot遵循表现与性能平衡信条.在这个表现的世界中,它们总是有许多约定俗成的东西,主要是在用执行速度换取可用性与扩展性方面.下面是一些实际的例子: 高效地渲染对象是比 ...

  7. 03_通过OpenHelper获取SqliteDatabase对象

    MyOpenHelper openHelper = new MyOpenHelper(this); 类似于java的File file = new File();只是声明这个东西,但是文件还并没有真正 ...

  8. Ubuntu&nbsp;12.04&nbsp;Eclipse设…

    Ubuntu 12.04 Eclipse设置(黑色背景解决) 分类: ubuntu2012-11-21 10:47 252人阅读 评论(0) 收藏 举报 eclipseEclipseubuntuUbu ...

  9. SQL中的row_number() over()解释

    有一个面试题目, 有一张表,如下: event_type value time : - : : : : : 需要按照event_type排序,返回同一个event_type的,最近时间和次近时间的两个 ...

  10. debian linux中文桌面系统安装

    一.基本系统安装 1 .安装光盘:可以到http://debian.cn99.com去下载ISO,我是之前从官方网站下载的.一只载第一张光盘即可.用NERO烧录成光碟. 2.将安装光盘放驱,并在BIO ...