使用 std::mutex 实现类交换
Implementing swap for class with std::mutex
>假设我们有一个带有std::mutex
的class
:
class Foo
{
std::mutex mutex_;
std::string str_;
// other members etc
public:
friend void swap(Foo& lhs, Foo& rhs) noexcept;
}
在这里实现swap
方法的适当方法是什么?是否需要/安全地单独锁定每个互斥锁,然后交换所有内容?例如
void swap(Foo& lhs, Foo& rhs) noexcept
{
using std::swap;
std::lock_guard<std::mutex> lock_lhs {lhs.mutex_}, lock_rhs {rhs.mutex_};
swap(ls.str_, rhs.str_);
// swap everything else
}
我已经看到在 C++17 中,std::lock_guard
会有一个构造函数采用多个互斥体来避免死锁,但我不确定这是否是这里的问题?
您可以使用
std::lock()
以非死锁方式获取锁。
如果你想使用std::lock_guard
,让他们采用一旦拿走的锁:
std::lock(lhs.mutex_, rhs.mutex_);
std::lock_guard<std::mutex> lock_a(lhs.mutex_, std::adopt_lock);
std::lock_guard<std::mutex> lock_b(rhs.mutex_, std::adopt_lock);
//swap actions
swap(ls.str_, rhs.str_);
如果你更喜欢std::unique_lock
,那么在不锁定的情况下构造它们,然后调用std::lock()
来锁定它们(这也适用于std::lock_guard
):
std::unique_lock<std::mutex> lock_a(lhs.mutex_, std::defer_lock);
std::unique_lock<std::mutex> lock_b(rhs.mutex_, std::defer_lock);
std::lock(lock_a, lock_b);
//swap actions
swap(ls.str_, rhs.str_);
在这两种情况下,都应首先测试lhs
和rhs
是否为同一对象,因为将std::lock
与一个互斥锁一起使用两次是未定义的行为:
if (&lhs == &rhs)
return;
我认为您的交换实现不安全。如果另一种算法尝试先锁定rhs.mutex_
然后lhs.mutex_
,则最终可能会陷入死锁。请尝试std::lock()
。
相关文章:
- 对象内部有大量数据容器,实现更高效的对象交换
- 实现交换/复制功能:有没有更好的方法
- 实现了用于滤波器设计的remez交换算法
- 交换对象不实现移动语义时的交换函数
- 在 C++11 中实现复制和交换习语的更好方法
- 替换C 中内置类型的交换实现
- 在低级别实现交换复制位时可能会出现什么问题
- 交换实现:效率和适用范围?
- 在复制和交换习惯用法中实现交换
- 交换接口的实现
- 字节交换方面的一般交换实现
- 在什么情况下,运算符=应该用左值/右值重载而不是复制和交换来实现
- 根据getcontext和setcontext实现交换上下文
- 如何在对象类型未知时实现交换函数
- std::sort 如何仅使用迭代器实现交换操作
- 使用 std::mutex 实现类交换
- 这是交换(多线程)的异常安全实现吗
- 用用户实现的交换来交换std::函数
- 原子比较和交换实现
- GCC 列表节点交换实现过于复杂