使用std :: mutex实现类的交换

Dan*_*iel 13 c++ multithreading swap mutex c++11

假设我们有class一个std::mutex:

class Foo
{
    std::mutex mutex_;
    std::string str_;
    // other members etc
public:
    friend void swap(Foo& lhs, Foo& rhs) noexcept;
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

我已经看到在C++ 17中,std::lock_guard将有一个构造函数采用多个互斥锁来避免死锁,但我不确定这是否是一个问题?

小智 11

您可以使用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_);
Run Code Online (Sandbox Code Playgroud)

如果你愿意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_);
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,您应该首先测试lhs并且rhs是同一个对象,因为使用std::lock一个互斥锁两次是未定义的行为:

if (&lhs == &rhs)
    return;
Run Code Online (Sandbox Code Playgroud)