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_variablecondition_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=1;   
        while(true)
        {               
                std::this_thread::sleep_for (chrono::milliseconds (15));               
                long element=interlock.fetch_add (1);//【1】
                lockBuffer.lock ();
                while(buffer.size()==10 && 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 0;
}

运行结果:

这个 不是我的 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 = 0; i < 5; ++i) {
            std::this_thread::sleep_for(std::chrono:: seconds(1));
            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 0; }

运行结果:
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 = 0;                //全局共享变量

void *producer(void*ptr){//生产数据
    int i;
    for(i=1;i<=MAX;i++){
        pthread_mutex_lock(&the_mutex);//互斥使用 缓冲区buffer
        while(buffer !=0)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(0);//over 线程
}

void *consumer(void *ptr){//消费数据
    int i;
    for(i=1;i<=MAX;i++){
        sleep(3);
        pthread_mutex_lock(&the_mutex);//互斥使用缓冲区
        printf("Is consumering \n");
        while(buffer==0)pthread_cond_wait(&condc,&the_mutex);
        buffer = 0;                //从缓冲区取出数据
        pthread_cond_signal(&condp);//唤醒生产者
        pthread_mutex_unlock(&the_mutex);////释放锁   就是释放了缓冲区buffer 
    }    
    pthread_exit(0);//over 线程
}

int main(int argc,char**argv)
{
    pthread_t pro,con;
    pthread_mutex_init(&the_mutex,0);
    pthread_cond_init(&condc,0);
    pthread_cond_init(&condp,0);
    
    pthread_create(&con,0,consumer,0);
    pthread_create(&pro,0,producer,0);

    pthread_join(pro,0);//回收线程资源
    pthread_join(con,0);
    
    pthread_cond_destroy(&condc);//销毁条件变量
    pthread_cond_destroy(&condp);
    
    pthread_mutex_destroy(&the_mutex);//销毁锁

    return 0;
}
已经进过测试 Linux Ok!!!!!!!!!!!!!!

就先到这里吧!!!

 

posted on 2017-11-05 00:33  zhangkele  阅读(284)  评论(0编辑  收藏  举报

导航