zoukankan      html  css  js  c++  java
  • c++11の条件变量

    一、条件变量的引入

    std::condition_variable 解决了死锁并且控制的资源的访问顺序二避免不必要的等待。当互斥操作不够用而引入的。比如,线程可能需要等待某个条件为真才能继续执行,而一个忙等待循环中可能会导致所有其他线程都无法进入临界区使得条件为真时,就会发生死锁。所以,condition_variable实例被创建出现主要就是用于唤醒等待线程从而避免死锁。std::condition_variable的 notify_one()用于唤醒一个线程;notify_all() 则是通知所有线程。

    二、下面是一个引用的例子

    假设想实现一个简单的消费者生产者模型,一个线程往队列中放入数据,一个线程往队列中取数据,取数据前需要判断一下队列中确实有数据,由于这个队列是线程间共享的,所以,需要使用互斥锁进行保护,一个线程在往队列添加数据的时候,另一个线程不能取,反之亦然。
    一般的:
    std::deque<int> q;
    std::mutex mu;
    
    void function_1() {
        int count = 10;
        while (count > 0) {
            std::unique_lock<std::mutex> locker(mu);
            q.push_front(count);
            std::cout << "t1 put a value : " << count << std::endl;
            locker.unlock();
            std::this_thread::sleep_for(std::chrono::seconds(1));
            count--;
        }
    }
    
    void function_2() {
        int data = 0;
        while (data != 1) {
            std::unique_lock<std::mutex> locker(mu);
            if (!q.empty()) {
                data = q.back();
                q.pop_back();
                locker.unlock();
                std::cout << "t2 got a value from t1: " << data << std::endl;
            }
            else {
                locker.unlock();
            }
        }
    }
    int main() {
        std::thread t1(function_1);
        std::thread t2(function_2);
        t1.join();
        t2.join();
        return 0;
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));表示延时1s,所以这个生产的过程是很慢的;function_2函数是消费者,存在着一个while循环,只有在接收到表示结束的数据的时候,才会停止,每次循环内部,都是先加锁,判断队列不空,然后就取出一个数,最后解锁。所以说,在1s内,做了很多无用功!这样的话,单核CPU占用率会很高,可能达到100%。
    // threadTest.cpp: 定义控制台应用程序的入口点。
    #include "stdafx.h"
    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <string>
    #include <fstream>
    #include <deque>
    #include <condition_variable>
    
    using namespace std;
    
    
    std::deque<int> q;
    std::mutex mu;
    std::condition_variable cond;
    
    void function_1() 
    {
        int count = 10;
        while (count>0)
        {
            std::unique_lock<mutex> locker(mu);
            q.push_back(count);
            locker.unlock();
            cond.notify_all();
            std::this_thread::sleep_for(chrono::seconds(1));
            count--;
        }
    
    }
    
    void funciton_2() 
    {
        int data = 0;
        while (data != 1)
        {
            std::unique_lock<mutex> locker(mu);
            cond.wait(locker, [](){return !q.empty(); }); //  while(q.empty()) {cond.wait(locker); }// Unlock mu and wait to be notified 等同写法
            data = q.back(); 
    q.pop_back();
    locker.unlock();
    cout
    << "t2 get a value form t1 " << data << endl; }
    }

    int main() {
    thread t1(function_1);
    thread t2(funciton_2);
    t1.join();
    t2.join();
    std::getchar();

    return 0; }

    多线程一----多线程的应用

    多线程二----简单线程管理

    多线程三----数据竞争和互斥对象

    多线程四----死锁和防止死锁

    多线程五----unick_lock和once_flag

    多线程六----条件变量

    多线程七----线程间通信

  • 相关阅读:
    JAVA类与对象(一)----基础概念理解
    JAVA数组
    JAVA算术运算符、关系运算符和位运算符
    JAVA数据类型
    JAVA配置环境变量
    C#中怎么生成36位的GUID
    jqAjax
    二进制1的个数
    成绩转换
    对决
  • 原文地址:https://www.cnblogs.com/xietianjiao/p/10457962.html
Copyright © 2011-2022 走看看