可以将 std::condition_variable 与 std::lock_guard 一起使用吗?
Is possible to use std::condition_variable with std::lock_guard?
我正在使用这样的 std::condition_variable
combined with a std::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::unique_lock
自动 unlocks itself in destructor,如果它被锁定。
不,如果与 std::condition_variable
一起使用,则需要 std::unique_lock
。 std::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
}
对条件变量 wait()
的任何调用将始终需要 lock()
和 unlock()
基础 mutex
。由于包装器 lock_guard<>
不提供这些功能,因此它 永远不会 与 wait()
.
一起使用
您仍然可以基于 lock_guard<>
编写您自己的简单互斥包装器,并添加 2 个必要的方法。此外,您还必须使用 condition_variable_any
,它接受任何带有 lock()/unlock() 接口的 lock/mutex:
#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::condition_variable
combined with a std::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::unique_lock
自动 unlocks itself in destructor,如果它被锁定。
不,如果与 std::condition_variable
一起使用,则需要 std::unique_lock
。 std::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
}
对条件变量 wait()
的任何调用将始终需要 lock()
和 unlock()
基础 mutex
。由于包装器 lock_guard<>
不提供这些功能,因此它 永远不会 与 wait()
.
您仍然可以基于 lock_guard<>
编写您自己的简单互斥包装器,并添加 2 个必要的方法。此外,您还必须使用 condition_variable_any
,它接受任何带有 lock()/unlock() 接口的 lock/mutex:
#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 ...
...