std::unique_lock 移动语义
Posted
技术标签:
【中文标题】std::unique_lock 移动语义【英文标题】:std::unique_lock move semantic 【发布时间】:2020-01-15 19:12:05 【问题描述】:请帮我检查一下我对std::unique_lock
移动语义的理解是否正确。
假设我有一个函数myFunc
,它需要在执行开始时获取一个互斥锁。
这个函数是从不同的函数调用的,其中一些函数,例如myWrapper1
在调用 myFunc
之前持有相同的互斥锁。
有时我需要在myFunc
的作用域退出时不释放这个锁。
typedef std::unique_lock<std::mutex> MyLock;
class Example2
std::mutex m_data_mutex;
MyLock&& myFunc(MyLock&& lk)
bool was_lock = lk.owns_lock();
if( !was_lock ) lk.lock();
std::cout << "myFunc" << std::endl;
if( !was_lock ) lk.unlock();
return std::move(lk);
void myWrapper1()
MyLock lk(m_data_mutex);
std::cout << "1" << std::endl;
lk = myFunc(std::move(lk));
std::cout << "2" << std::endl;
void myWrapper2()
MyLock lk(m_data_mutex);
std::cout << "1" << std::endl;
lk.unlock();
lk = myFunc(std::move(lk));
std::cout << "2" << std::endl;
lk.lock();
std::cout << "3" << std::endl;
;
所以问题是:
-
对于
myWrapper1
,保证MyLock
只会在myWrapper1
作用域结束时被释放,不是吗?
我是否使用正确的习语来解决这个问题?
【问题讨论】:
1.是的,2. 不。从技术上讲,您只是将 lk 分配给自己,这是没有意义的。 @osuka_ std::move 移动是错觉。 std::move 只需要对对象的右值引用。由于引用也从 myFunc 返回,因此不会发生所有权更改。 @OlhaPavliuk 最好 void myFunc(MyLock& lk) 并在传递 lk 时删除 std::move 只会让人感到困惑。 @OlhaPavliuk 这两个例子都没有发生任何事情,因为第二个锁永远不会被实例化。没有调用构造函数;只有当锁是“通过副本”(即,不是通过引用)传递时,所有权才会转移 - 然后,将调用 move c'tor。 @osuka_ 谢谢,我知道了! 【参考方案1】:你有什么理由不能做这样的事情吗? IMO,这比在所有者之间移动锁要干净得多。
std::mutex my_lock;
void myFunc_locked()
...do something that requires my_lock to be locked...
void myFunc()
std::lock_guard<std::mutex> guard(my_lock);
myFunc_locked();
void myWrapper1()
std::lock_guard<std::mutex> guard(my_lock);
...do something else that requires my_lock to be locked...
myFunc_locked();
void myWrapper2()
...
myFunc();
或者,按照@Nevin 的建议进行操作。也许更干净:
std::mutex my_lock;
void myFunc(std::lock_guard<std::mutex>> const& guard)
...do something that requires my_lock to be locked...
void myFunc()
std::lock_guard<std::mutex> guard(my_lock);
myFunc(guard);
void myWrapper1()
std::lock_guard<std::mutex> guard(my_lock);
...do something else that requires my_lock to be locked...
myFunc(guard);
void myWrapper2()
...
myFunc();
【讨论】:
谢谢,这是一个好方法。但是有时很难看出在调用myFunc
之前是否没有获得相同的锁,并且可能会发生死锁。其实,我是在陷入僵局之后才开始探索这个问题的。以上是关于std::unique_lock 移动语义的主要内容,如果未能解决你的问题,请参考以下文章