【发布时间】:2024-01-09 23:32:01
【问题描述】:
请帮我检查一下我对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_ 谢谢,我知道了!
标签: c++ multithreading c++11 mutex