是否可以将std :: condition_variable与std :: lock_guard一起使用?

时间:2016-11-13 18:59:06

标签: c++ c++11 mutex condition-variable

我正在使用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::unique_lock代替std::lock_guard这可以减轻我每次手动解锁锁定的麻烦时间我用它。

3 个答案:

答案 0 :(得分:4)

不,如果与std::unique_lock一起使用,则需要std::condition_variablestd::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

答案 1 :(得分:4)

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

仍然可以根据lock_guard<>编写自己的简单互斥包装器,并添加2个必要的方法。此外,您必须使用condition_variable_any,它接受​​带锁()/ 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 ...
...

答案 2 :(得分:2)

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

std::unique_lock自动unlocks itself in destructor,如果已被锁定。