gpt4 book ai didi

c++ - 使用 std::mutex 模拟死锁

转载 作者:太空狗 更新时间:2023-10-29 23:49:16 28 4
gpt4 key购买 nike

我有以下示例:

template <typename T>
class container
{
public:
std::mutex _lock;
std::set<T> _elements;

void add(T element)
{
_elements.insert(element);
}

void remove(T element)
{
_elements.erase(element);
}
};

void exchange(container<int>& cont1, container<int>& cont2, int value)
{
cont1._lock.lock();
std::this_thread::sleep_for(std::chrono::seconds(1));

cont2._lock.lock();

cont1.remove(value);
cont2.add(value);

cont1._lock.unlock();
cont2._lock.unlock();
}

int main()
{
container<int> cont1, cont2;

cont1.add(1);
cont2.add(2);

std::thread t1(exchange, std::ref(cont1), std::ref(cont2), 1);
std::thread t2(exchange, std::ref(cont2), std::ref(cont1), 2);

t1.join();
t2.join();

return 0;
}

在这种情况下,我遇到了一个僵局。但是当我使用 std::lock_guard 而不是手动锁定和解锁互斥锁时,我没有死锁。为什么?

void exchange(container<int>& cont1, container<int>& cont2, int value)
{
std::lock_guard<std::mutex>(cont1._lock);
std::this_thread::sleep_for(std::chrono::seconds(1));

std::lock_guard<std::mutex>(cont2._lock);

cont1.remove(value);
cont2.add(value);
}

最佳答案

你的两个代码片段没有可比性。第二个片段锁定并立即解锁每个互斥体,因为临时 lock_guard 对象在分号处被销毁:

std::lock_guard<std::mutex>(cont1._lock);  // temporary object

使用锁守卫的正确方法是为它们创建作用域变量:

{
std::lock_guard<std::mutex> lock(my_mutex);

// critical section here

} // end of critical section, "lock" is destroyed, calling mutex.unlock()

(请注意,还有一个相似但不同的常见错误:

std::mutex mu;
// ...
std::lock_guard(mu);

声明了一个名为mu 的变量(就像int(n);)。但是,此代码格式错误,因为 std::lock_guard 没有默认构造函数。但它会编译,比如说,std::unique_lock,而且它也不会最终锁定任何东西。)

现在来解决真正的问题:如何以一致的顺序一次锁定多个互斥锁?在整个代码库中,甚至在未来用户的代码库中,甚至在您的示例所示的本地情况下,就单个锁定顺序达成一致可能是不可行的。在这种情况下,使用 std::lock 算法:

std::mutex mu1;
std::mutex mu2;

void f()
{
std::lock(mu1, mu2);

// order below does not matter
std::lock_guard<std::mutex> lock1(mu1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(mu2, std::adopt_lock);
}

在 C++17 中有一个名为 scoped_lock 的新可变锁保护模板:

void f_17()
{
std::scoped_lock lock(mu1, mu2);

// ...
}

scoped_lock的构造函数使用与std::lock相同的算法,因此两者可以兼容使用。

关于c++ - 使用 std::mutex 模拟死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43538629/

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