std::condition_variable可以与std::lock_guard一起使用

Is possible to use std::condition_variable with std::lock_guard?

本文关键字:std guard 一起 lock condition variable      更新时间:2023-10-16

我正在使用这样的std::condition_variablestd::unique_lock组合。

std::mutex a_mutex;
std::condition_variable a_condition_variable;
std::unique_lock<std::mutex> a_lock(a_mutex);
a_condition_variable.wait(a_lock, [this] {return something;});
//Do something
a_lock.unlock();

很好。据我所知,std::condition_variable接受std::unique_lock等待。但是,我试图将它与std::lock_guard结合起来,但不能。

我的问题是:是否有可能用std::lock_guard代替std::unique_lock ?这可以减轻我每次使用它时手动解锁锁。

不,如果与std::condition_variable一起使用,则需要std::unique_lockstd::lock_guard可能有更少的开销,但它不能与std::condition_variable一起使用。

但是std::unique_lock不需要手动解锁,当它超出范围时也会解锁,就像std::lock_guard一样。所以等待代码可以写成:

std::mutex a_mutex;
std::condition_variable a_condition_variable;
{
    std::unique_lock<std::mutex> a_lock(a_mutex);
    a_condition_variable.wait(a_lock, [this] {return something;});
    //Do something
}

见http://en.cppreference.com/w/cpp/thread/unique_lock

任何对条件变量wait()的调用都将始终需要对lock()unlock()调用基础mutex。由于包装器lock_guard<>不提供这些函数,因此永远不能wait()一起使用。

您仍然可以基于lock_guard<>编写自己的简单互斥锁包装器,并添加两个必要的方法。另外,您必须使用condition_variable_any,它接受任何具有lock()/unlock()接口的锁/互斥锁:

#include <mutex>
template<typename _mutex_t>
class my_lock_guard
{
public:
    explicit my_lock_guard(_mutex_t & __m) : __mutex(__m)
    { __mutex.lock(); }
    my_lock_guard(_mutex_t & __m, std::adopt_lock_t) : __mutex(__m)
    { } // calling thread owns mutex
    ~my_lock_guard()
    { __mutex.unlock(); }
    void lock()
    { __mutex.lock(); }
    void unlock()
    { __mutex.unlock(); }   
    my_lock_guard(const my_lock_guard &) = delete;
    my_lock_guard& operator=(const my_lock_guard &) = delete;
private:
    _mutex_t &  __mutex;
};

然后:

#include <condition_variable>
...
std::mutex m;
my_lock_guard<std::mutex> lg(m);
std::condition_variable_any cva;
cva.wait(lg, [] { return something;});  
// do something ...
...

不可能,但你实际上不需要。

std::unique_lock在析构函数中自动解锁,如果它被锁定。