在 C 中处理可移动类型中的互斥体
正如您所提到的,std::mutex 既不可移动也不可复制,在以下情况下会带来挑战:使用持有互斥体的类。要使类型可移动,同时保持线程安全,请考虑以下方法:
创建一个移动构造函数,使用 WriteLock 锁定要从 (a) 移动的对象的互斥体:
A(A&& a) { WriteLock rhs_lk(a.mut_); field1_ = std::move(a.field1_); field2_ = std::move(a.field2_); }
移动赋值运算符比较棘手,因为其他线程可能正在访问赋值的左侧或右侧:
A& operator=(A&& a) { if (this != &a) { WriteLock lhs_lk(mut_, std::defer_lock); WriteLock rhs_lk(a.mut_, std::defer_lock); std::lock(lhs_lk, rhs_lk); field1_ = std::move(a.field1_); field2_ = std::move(a.field2_); } return *this; }
如果需要支持复制语义,请创建一个复制构造函数来锁定要复制的对象的互斥体( )使用 ReadLock:
A(const A& a) { ReadLock rhs_lk(a.mut_); field1_ = a.field1_; field2_ = a.field2_; }
如果您还需要复制赋值运算符,遵循类似的模式:
A& operator=(const A& a) { if (this != &a) { WriteLock lhs_lk(mut_, std::defer_lock); ReadLock rhs_lk(a.mut_, std::defer_lock); std::lock(lhs_lk, rhs_lk); field1_ = a.field1_; field2_ = a.field2_; } return *this; }
保护访问类状态的成员和自由函数对于线程安全至关重要。例如,下面是一个交换函数:
friend void swap(A& x, A& y) { if (&x != &y) { WriteLock lhs_lk(x.mut_, std::defer_lock); WriteLock rhs_lk(y.mut_, std::defer_lock); std::lock(lhs_lk, rhs_lk); using std::swap; swap(x.field1_, y.field1_); swap(x.field2_, y.field2_); } }
最后,回想一下 C 14 中的 std::shared_timed_mutex 允许在多个线程尝试从同一对象进行复制构造的情况下进行可能的优化。
以上是如何用 C 语言制作带有内部互斥体的可移动类型?的详细内容。更多信息请关注PHP中文网其他相关文章!