C++ lock_guard, unique_guard, condition_variable

lock_guard vs unique_guard

lock_guard: 提供了一种RAII机制,在一个scope块中拥有一个mutex。当创建一个lock_guard对象的时候,它将会尝试拥有mutex,当离开lock_guard对象创建的scope的时候,lock_guard对象被析构并且释放mutex。lock_guard是不可拷贝的。

unique_lock: unique_lock是一个通用的mutex封装器,通常与条件变量一起使用,能够手动lock()unlock()(提供了相关API)。支持移动语义,但不可拷贝。
参考文章

condition_variable

condition_variable:是一个同步元语,与mutex一起使用可以阻塞一个或多个线程,直到有一个线程修改了一个共享变量(条件)并通知其他条件变量。

线程如果想要修改共享变量(条件),必须满足以下条件:

  1. 获取到mutex(一般是通过lock_guard)
  2. 当持有锁的时候修改共享变量
  3. 通过条件变量调用notify_one或notify_all(能够在释放锁之后再调用)

即使共享变量是原子的,也必须要再拥有锁的时候修改,才能正确的通知到正在等待的线程。任何想要在条件变量上等待的线程,必须满足以下条件:

  1. 使用unique_lock<mutex>来保护共享变量

  2. 做下面的事情之一:

    1. 检查条件,以防它已经更新并通知
    2. 在条件变量上调用wait, wait_for或者wait_until(原子的释放mutex并挂起线程,直到条件变量被通知、时间过期或假唤醒(spurious wakeup),然后在返回前自动获取mutex)
    3. 检查条件,如果条件不满足继续等待

    1. 使用自己重载的wait, wait_for和wait_until,要执行2.2中相同的三个步骤。

条件变量只和unique_lock<mutex>一起工作。

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <unistd.h>

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

void worker_thread() {
    unique_lock<mutex> lk(m);
    cv.wait(lk, []{return ready;});
  	// 如果使用wait_for,则等待一段时间或者条件满足之后就会继续执行
		// cv.wait_for(lk, chrono::seconds(5), []{return ready;});
  
    cout << "worker thread is processing data" << endl;
    data += " after processing";
    processed = true;
    cout << "worker thread signals data processing completed" << endl;
    lk.unlock();
    cv.notify_one();
}

int main() {
    thread worker(worker_thread);
    data = "Example data";
    sleep(20);
    {
        lock_guard<mutex> lk(m);
        ready = true;
        cout << "main() signals data ready for processing" << endl;
    }
    cv.notify_one();

    {
        unique_lock<mutex> lk(m);
        cv.wait(lk, []{return processed;});
        cout << "Back in main(), data=" << data << endl;
    }
    worker.join();
}

编译及其输出结果

$ g++ -o test_condition_variable test_condition_variable.cpp -lpthread
# 使用wait()
$ ./test_condition_variable
main() signals data ready for processing
worker thread is processing data	# 等到主线程将条件设置为true子线程才继续执行
worker thread signals data processing completed
Back in main(), data=Example data after processing
# 使用wait_for(),时间到期或条件满足,这次测试的是时间到期
$ ./test_condition_variable
worker thread is processing data	# 子线程等到5秒后,即使条件没有满足也继续执行了
worker thread signals data processing completed
main() signals data ready for processing
Back in main(), data=Example data after processing
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值