Fre*_*urk 6 c++ mutex copy-and-swap c++11
借用Howard Hinnant的例子并将其修改为使用copy-and-swap,这是op =线程安全吗?
struct A {
A() = default;
A(A const &x); // Assume implements correct locking and copying.
A& operator=(A x) {
std::lock_guard<std::mutex> lock_data (_mut);
using std::swap;
swap(_data, x._data);
return *this;
}
private:
mutable std::mutex _mut;
std::vector<double> _data;
};
Run Code Online (Sandbox Code Playgroud)
我相信这个线程安全(记住op =的参数是通过值传递的),我能找到的唯一问题是在地毯下扫描的那个:复制ctor.但是,它是一种罕见的类,它允许复制赋值而不是复制构造,因此在两种选择中都存在同样的问题.
鉴于自我分配是如此罕见(至少在这个例子中)我不介意额外的副本如果发生,考虑这个!=&rhs的潜在优化要么可以忽略不计,要么是悲观化.与原始策略(下面)相比,是否还有其他理由更喜欢或避免它?
A& operator=(A const &rhs) {
if (this != &rhs) {
std::unique_lock<std::mutex> lhs_lock( _mut, std::defer_lock);
std::unique_lock<std::mutex> rhs_lock(rhs._mut, std::defer_lock);
std::lock(lhs_lock, rhs_lock);
_data = rhs._data;
}
return *this;
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我认为这简洁地处理了复制文件,至少在本课程中,即使它有点迟钝:
A(A const &x) : _data {(std::lock_guard<std::mutex>(x._mut), x._data)} {}
Run Code Online (Sandbox Code Playgroud)
我相信你的作业是线程安全的(当然假设课外没有参考).它相对于const A&变体的性能可能取决于A.我认为对于许多A来说,如果不是更快,你的重写将同样快.我有一个很好的反例是std :: vector(和类似的类).
std :: vector的容量不参与其值.如果lhs相对于rhs具有足够的容量,那么重复使用该容量而不是将其丢弃到临界状态,可以获得性能提升.
例如:
std::vector<int> v1(5);
std::vector<int> v2(4);
...
v1 = v2;
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,如果v1保持其分配的能力,则可以在没有堆分配或释放的情况下完成分配.但是如果vector使用交换习惯用法,那么它会进行一次分配和一次释放.
我注意到,就线程安全而言,两种算法都锁定/解锁两个锁.虽然交换变体避免了同时锁定它们的需要.我相信平均锁定两者的成本很小.但在竞争激烈的用例中,它可能成为一个问题.
| 归档时间: |
|
| 查看次数: |
1816 次 |
| 最近记录: |