栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

[c++多线程并发 基础入门] 1.3条件变量condition

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[c++多线程并发 基础入门] 1.3条件变量condition

1.无条件变量时
#include 
#include 
#include 
#include 
#include 

std::mutex mtx;
std::deque q;

//producer
void task1()
{
    int i = 0;
    
    while(true)
    {
        std::unique_lock lock(mtx);
        q.push_back(i);
        //this thread delay 10ms
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        
        if(i < 99)
        {
            i++;
        }
        else
        {
            i = 0;
        }
    }
}

//consumer
void task2()
{
    int data = 0;
    
    while(true)
    {
        std::unique_lock lock(mtx);
        
        if(!q.empty())
        {
            data = q.front();
            q.pop_front();
            std::cout<< "get value from que: "<
    std::thread t1(task1);
    std::thread t2(task2);
    
    t1.join();
    t2.join();
    
    return 0;
}

使用延时std::this_thread::sleep_for(std::chrono::milliseconds(10)); 表示当前线程休眠一段时间,休眠期间不与其他线程竞争CPU,根据线程需求,等待若干时间。

延时过长,消费者线程不能及时的从队列里面取数据
延时过短,对CPU的占用率不能很大缓解

2条件变量

例子:

#include 
#include 
#include 
#include 
#include 
#include 

std::mutex mtx;
std::deque q;
std::condition_variable cv;

//producer
void task1()
{
    int i = 0;
    
    while(true)
    {
        std::unique_lock lock(mtx);
        
        q.push_back(i);
        cv.notify_one();
        
        if(i < 20)
        {
            i++;
        }
        else
        {
            i = 0;
        }
    }
}

//consumer
void task2()
{
    int data = 0;
    
    while(true)
    {
        std::unique_lock lock(mtx);
        
        if(q.empty())
        {
            cv.wait(lock);
            //cv.wait(lock) 相当于下面两行
            //lock.unlock();
            //cv.wait();
        }
        
        if(!q.empty())
        {
            data = q.front();
            q.pop_front();
            std::cout<< "get value from que: "<

    std::thread t1(task1);
    std::thread t2(task2);

    t1.join();
    t2.join();
    
    return 0;
}

macOS xcode 运行结果:
get value from que: 0
get value from que: 1
get value from que: 2
get value from que: 3
get value from que: 4
get value from que: 5
get value from que: 6
get value from que: 7
get value from que: 8
get value from que: 9
get value from que: 10
get value from que: 11
get value from que: 12
get value from que: 13
get value from que: 14
get value from que: 15
get value from que: 16
get value from que: 17
get value from que: 18
get value from que: 19
get value from que: 20
get value from que: 0
get value from que: 1
get value from que: 2
get value from que: 3
get value from que: 4
get value from que: 5
get value from que: 6
get value from que: 7
get value from que: 8
get value from que: 9
get value from que: 10
get value from que: 11
get value from que: 12
get value from que: 13
get value from que: 14
get value from que: 15
get value from que: 16
get value from que: 17
get value from que: 18
get value from que: 19
get value from que: 20
get value from que: 0
get value from que: 1
get value from que: 2
get value from que: 3
get value from que: 4
get value from que: 5
get value from que: 6
get value from que: 7
get value from que: 8
get value from que: 9
get value from que: 10
get value from que: 11
get value from que: 12
get value from que: 13
get value from que: 14
get value from que: 15
get value from que: 16
get value from que: 17
get value from que: 18
get value from que: 19
get value from que: 20
get value from que: 0
get value from que: 1
get value from que: 2
…
…

3虚假唤醒
#include 
#include 
#include 
#include 
#include 
#include 

std::mutex mtx;
std::deque q;
std::condition_variable cv;

//producer
void task1()
{
    int i = 0;
    
    while(true)
    {
        std::unique_lock lock(mtx);
        
        q.push_back(i);
        cv.notify_one();
        
        if(i < 2000000000)
        {
            i++;
        }
        else
        {
            i = 0;
        }
    }
}

//consumer1
void task2()
{
    int data = 0;
    
    while(true)
    {
        std::unique_lock lock(mtx);
        
        if(q.empty())
        {
            cv.wait(lock);//意思是下面两句,解锁再等待
            //lock.unlock();
            //cv.wait();
        }
        
        data = q.front();
        q.pop_front();
        std::cout<< "get value from que: "<
    int data = 0;
    
    while(true)
    {
        std::unique_lock lock(mtx);
        
        if(q.empty())
        {
            cv.wait(lock);//意思是下面两句,解锁再等待
            //lock.unlock();
            //cv.wait();
        }
        
        data = q.front();
        q.pop_front();
        std::cout<< "get value from que: "<

    std::thread t1(task1);
    std::thread t2(task2);
    std::thread t3(task2);
    
    t1.join();
    t2.join();
    t3.join();
    
    return 0;
}

以上可能造成虚假唤醒,当生产者q.push_back(i);时:消费者1判断队列不为空 后取出队列头的元素并移除,生产者notify_one后通知消费者2,消费者2从wait中唤醒,然后又去取队列头部数据,此时队列头部数据已经被消费者1移除了,报错,这就是虚假唤醒

解决方法:
把消费者1, 消费者2中的 if改成while

 if(q.empty())
 {
     cv.wait(lock);//意思是下面两句,解锁再等待
     //lock.unlock();
     //cv.wait();
 }

改成:

 while(q.empty())
 {
     cv.wait(lock);//意思是下面两句,解锁再等待
     //lock.unlock();
     //cv.wait();
 }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/954207.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号