【C++11多线程】线程同步


一个线程要等待另一个线程完成任务,确定完成任务的方法有几种。第一种是持续检查mutex,这种方法显然很浪费资源;第二种是每隔一段时间进行一次检查;第三种方案是使用条件变量(condition variable)

condition variable

标准库对条件变量提供了两种实现:std::condition_variable和std::condition_variable_any,前者仅限和std::mutex工作,而后者可以与任何满足最低标准的mutex工作

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

std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;

void f()
{
    std::unique_lock<std::mutex> l(m); // 传给wait的只能是std::unique_lock
    cv.wait(l, [] { return ready; }); // 第二个参数为false时解锁mutex阻塞线程
    // 当收到其他线程notify_one时wait会被唤醒,这时会自动调用l.lock上锁,使unique_lock l恢复到wait之前的上锁状态持有该锁
    data += " after processing";
    processed = true;
    l.unlock();
    cv.notify_one();
}

int main()
{
    std::thread t(f);
    data = "data";
    {
        std::lock_guard<std::mutex> l(m);
        data += " ready";
        ready = true;
        cv.notify_one(); // 唤醒cv.wait,重新检查ready == true
    }
    {
        std::unique_lock<std::mutex> l(m);
        cv.wait(l, [] { return processed; });
    }
    std::cout << data; // data ready after processing
    t.join();
}

1.因为有假醒的可能,所以,每当条件变量被唤醒,都需要重新检查条件
2.condition_variable的构造函数失败,会抛出system_error异常,并夹带错误码resource_unavailable_try_again
3.condition_variable的复制和赋值都是不允许的
4.通知都会同步化,所以并发调用notify_one()和notify_all(),没有任何问题
5.所有等待condition_variable的线程必须使用相同的mutex
6.wait()成员函数调用之前,必须用unique_lock锁住互斥量,否则结果是未定义的
7.wait_for()和wait_until()有一个不接受判断式的版本,他们的返回值是以下枚举:
std::cv_status::timeout 如果发生超时
std::cv_status::no_timeout 如果发生通知
wait_for()和wait_until()有一个接受判断式的版本(判断式作为第三实参),他们返回判断式的执行结果
8.notify_all_at_thread_exit(cv,l)在调用线程退场的时候,调用notify_all(),为了在通知"等待线程"之前完成清理工作,这个清理工作绝不该造成阻塞

参考

1.https://downdemo.gitbook.io/cpp-concurrency-in-action-2ed
2.https://www.jianshu.com/p/2e82636885cc

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值