C++多线程同步-condition_variable

代码

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>



std::condition_variable cv_02;
std::mutex cv_m_02; // This mutex is used for three purposes:
                 // 1) to synchronize accesses to i
                 // 2) to synchronize accesses to std::cerr
                 // 3) for the condition variable cv
int i = 0;

void waits()
{
    std::unique_lock<std::mutex> lk(cv_m_02); // 因lock_guard不提供lock()和unlock()方法,在notify端调用了notify_all()或notify_one()时wait()/等待线程将会对条件进行测试,测试时会调用lock()和unlock(),此处不能使用lock_guard

    // cv_02.wait(lk, [] {return i == 1; });

    /*
    * 1. 获得锁: std::unique_lock<std::mutex> lk(cv_m_02),获得锁(构造unique_lock时调用lock()方法)的目的是用于对条件变量(如本例中的i)进行测试
    * 2. wait()将当前线程放入等待队列,并对lk(即cv_m_02)进行解锁(即调用unlock()),解锁目的是允许其他线程获得锁并对测试条件进行改变,并等待其他线程调用notify_one()/notify_all()唤醒
    * 3. 首次调用wait()时将对条件变量(如本例中的i)进行测试
    * 4. 当其他线程调用notify_one()/notify_all()时,wait()将重新获得锁并对条件(本例中的i是否为1)进行测,测试失败时再次释放锁(允许其他线程获得锁并对测试条件进行改变)
    * 5. 当wait()测试条件满足(如本例中的i=1),被唤醒后,重新获得锁(即调用lock()方法),当锁(本例的lk)所在作用域(如waits方法运行完)外时将被自动解锁(即lk虚构方法自动调用unlock()进行解锁)
    */
    cv_02.wait(lk, [] {
        if (i == 1) { // 条件测试成功,唤醒
            std::cerr << "thread-" << std::this_thread::get_id() << " wakeup... \n";
            return true;
        }
        else { // 条件测试失败,继续等待
            std::cerr << "thread-" << std::this_thread::get_id() << " condition is false, Waiting notify continue... \n";
            return false;
        }
     });

    std::cerr << "thread-" << std::this_thread::get_id() << " ...finished waiting. i == 1\n";
}

void signals()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lk(cv_m_02);
        std::cerr << "Notifying...\n";
    } // 作用域(注意一对大括号)外时,lk被释放(即cv_m_02被释放)外,其他线程可以获得锁(即本例中的cv_m_02)

    cv_02.notify_all(); // 唤醒所有等待线程,条件变量为i=0,等待线程测试条件将失败,继续等待
    //cv_02.notify_one(); // 唤醒一个等待线程,条件变量为i=0,等待线程测试条件将失败,继续等待

    std::this_thread::sleep_for(std::chrono::seconds(1));

    {
        std::lock_guard<std::mutex> lk(cv_m_02);
        i = 1;
        std::cerr << "Notifying again...\n";
    } // 作用域(注意一对大括号)外时,lk被释放(即cv_m_02被释放)外,其他线程可以获得锁(即本例中的cv_m_02)
    
    cv_02.notify_all(); // 唤醒所有等待线程,条件变量为i=1,所有等待线程将被唤醒
}

void test02()
{
    std::thread t1(waits), t2(waits), t3(waits), t4(signals);
    t1.join();
    t2.join();
    t3.join();
    t4.join();
}

int main()
{
    test02();
}

运行结果

thread-23988 condition is false, Waiting notify containue...
thread-4264 condition is false, Waiting notify containue...
thread-4812 condition is false, Waiting notify containue...
Notifying...
thread-23988 condition is false, Waiting notify containue...
Notifying again...
thread-23988 wakeup...
thread-23988 ...finished waiting. i == 1
thread-4812 wakeup...
thread-4812 ...finished waiting. i == 1
thread-4264 wakeup...
thread-4264 ...finished waiting. i == 1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneOnce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值