gpt4 book ai didi

c++ - 通过 copy-and-swap 分配与两个锁

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:25:47 24 4
gpt4 key购买 nike

借款Howard Hinnant's example并将其修改为使用 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;
};

我相信这是线程安全的(记住 op= 的参数是按值传递的),我能找到的唯一问题是隐藏在地毯下的问题:复制构造函数。但是,允许复制赋值但不允许复制构造的类很少见,因此该问题在两种替代方案中同样存在。

鉴于自赋值非常罕见(至少对于本示例而言),如果发生这种情况我不介意额外的拷贝,请考虑将此 != &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;
}

顺便说一下,我认为这简洁地处理了复制构造函数,至少对于这个类来说是这样,即使它有点迟钝:

A(A const &x) : _data {(std::lock_guard<std::mutex>(x._mut), x._data)} {}

最佳答案

我相信您的作业是线程安全的(当然假设没有课外引用)。它相对于 const A& 变体的性能可能取决于 A。我认为对于许多 A 来说,您的重写即使不是更快,也会同样快。我的最大反例是 std::vector(和类似的类)。

std::vector 具有不参与其值的容量。如果 lhs 相对于 rhs 有足够的容量,那么重用该容量而不是将其丢给临时工,可以在性能上取得胜利。

例如:

std::vector<int> v1(5);
std::vector<int> v2(4);
...
v1 = v2;

在上面的例子中,如果 v1 保持它的能力来做分配,那么分配可以在没有堆分配或释放的情况下完成。但是如果 vector 使用 swap idiom,那么它会进行一次分配和一次释放。

我注意到,就线程安全而言,两种算法都锁定/解锁两个锁。尽管交换变体避免了同时锁定它们的需要。我相信同时锁定两者的平均成本很小。但在竞争激烈的用例中,这可能会成为一个问题。

关于c++ - 通过 copy-and-swap 分配与两个锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5072082/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com