d3p*_*3pd 4 c++ multithreading deadlock c++11
我有一个人为的C++ 11线程死锁.这是通过使用具有多个线程池的两个单独函数来实现的.如何修复此示例以避免死锁?我认为该解决方案与锁定程序的一致排序有关.
#include <thread>
#include <mutex>
#include <iostream>
std::mutex kettle;
std::mutex tap;
#define THREAD_POOL 8
void kettle_tap(){
std::cout << "Locking kettle in " << std::this_thread::get_id() << std::endl;
// Lock the mutex kettle by creating and using lock_guard kettle_lock.
std::lock_guard<std::mutex> kettle_lock(kettle);
std::cout << "Locked kettle in " << std::this_thread::get_id() << std::endl;
std::cout << "Locking tap in " << std::this_thread::get_id() << std::endl;
// Lock the mutex tap by creating and using lock_guard tap_lock.
std::lock_guard<std::mutex> tap_lock(tap);
std::cout << "Locked tap in " << std::this_thread::get_id() << std::endl;
std::cout << "Filling kettle in " << std::this_thread::get_id() << std::endl;
}
void tap_kettle(){
std::cout << "Locking tap in " << std::this_thread::get_id() << std::endl;
// Lock the mutex tap by creating and using lock_guard tap_lock.
std::lock_guard<std::mutex> tap_lock(tap);
std::cout << "Locked tap in " << std::this_thread::get_id() << std::endl;
std::cout << "Locking kettle in " << std::this_thread::get_id() << std::endl;
// Lock the mutex kettle by creating and using lock_guard kettle_lock.
std::lock_guard<std::mutex> kettle_lock(kettle);
std::cout << "Locked kettle in " << std::this_thread::get_id() << std::endl;
std::cout << "Filling kettle in " << std::this_thread::get_id() << std::endl;
}
int main(){
std::thread pool[THREAD_POOL];
for (int t = 0; t < THREAD_POOL; t += 2){
pool[t] = std::thread(kettle_tap);
pool[t+1] = std::thread(tap_kettle);
}
for (int t = 0; t < THREAD_POOL; ++t){
pool[t].join();
}
std::cout << "Threads are all joined" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在你的情况都kettle_tap()和tap_kettle()应开始:
std::lock(tap, kettle);
Run Code Online (Sandbox Code Playgroud)
但是互斥参数的顺序并不重要,因此两个函数的顺序也不同.
锁定多个互斥锁
锁定作为参数传递的所有对象,并在必要时阻止调用线程.
该函数使用对其成员lock,try_lock和unlock的未指定的调用序列来锁定对象,以确保返回时锁定所有参数(不会产生任何死锁).
如果该函数无法锁定所有对象(例如因为其内部调用之一引发了异常),则该函数首先解锁所有成功锁定的对象(如果有),然后再失败.
稍后,如果您想将锁的所有权转移到std::lock_guard:
std::lock(tap, kettle);
std::lock_guard<std::mutex> kettle_lock(kettle, std::adopt_lock);
std::lock_guard<std::mutex> tap_lock(tap, std::adopt_lock);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4235 次 |
| 最近记录: |