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. C语言中数据类型和变量

    C语言中的数据类型 数据类型的本质,固定大小内存块的别名. 数组名代表数组首元素的地址. 数组首元素的地址,&代表整个数组的地址. 数组数据类型,怎么定义数据数组类型,定义数组类型指针,数组类 ...

  2. java中interface 的特性

    有时必须从几个类中派生出一个子类,继承它们所有的属性和方法.但是,Java不支持多重继承.有了接口,就可以得到多重继承的效果. 接口(interface)是抽象方法和常量值的定义的集合.从本质上讲,接 ...

  3. ubuntu c++ 关机 重启 挂起 API

    #include <unistd.h> #include <linux/reboot.h> int main() { reboot(LINUX_REBOOT_MAGIC1, L ...

  4. CodeForces - 1000E :We Need More Bosses(无向图缩点+树的直径)

    Your friend is developing a computer game. He has already decided how the game world should look lik ...

  5. Confd 配置指导

    Quick Start Guide Before we begin be sure to download and install confd. Select a backend confd supp ...

  6. 如何解压deb文件

    有两种方法: Bash代码 1.dpkg -x xx.deb /tmp/oo 注意:/tmp/oo为自己解压文件路径,可以随意指定路径 2.ar -vx xx.deb 这会解压出3个文件debian- ...

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

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

  8. this在方法赋值过程中无法保持(隐式丢失)

    在看<高级程序设计>(我的红宝书) P.183页时遇到下面一个问题 var name = "77"; var obj = { name: "88", ...

  9. PLSQ创建用户L

    1.首先使用dba权限角色登陆PLSQL 2.选择File-New-User   输入需要创建的账户及密码,选择表空间 3.一定要分配的权限:Role privileges 角色权限,至少分配conn ...

  10. hdu 4336 Card Collector (概率dp+位运算 求期望)

    题目链接 Card Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...