我正在自学一些关于并发编程的知识,特别是在C ++中使用互斥锁和线程。我写了下面的小例子:
#include <iostream>
#include <thread>
#include <mutex>
// #include <chrono>
std::mutex M1,M2;
void task_one () {
std::cout << "AAAA!\n";
M1.lock();
// std::cout << "M1 locked in A\n";
M2.lock();
// std::cout << "M2 locked in A\n";
std::cout << "BBBB!\n";
M2.unlock();
// std::cout << "M2 unlocked in A\n";
M1.unlock();
// std::cout << "M2 unlocked in A\n";
}
void task_two () {
std::cout << "CCCC!\n";
M2.lock();
// std::cout << "M2 locked in B\n";
M1.lock();
// std::cout << "M1 locked in B\n";
std::cout << "DDDD!\n";
// M1.unlock();
// std::cout << "M1 unlocked in B\n";
M2.unlock();
// std::cout << "M2 unlocked in B\n";
}
int main () {
std::thread th1 (task_one);
std::thread th2 (task_two);
th1.join();
th2.join();
// th1.detach();
// th2.detach();
// std::chrono::milliseconds timespan(10);
// std::this_thread::sleep_for(timespan);
return 0;
}
我希望此代码可以打印
AAAA!
CCCC!
,然后在task_one
尝试获取M2上的锁时死锁(因为task_two
已经获取了该锁)。
但是,它会打印
AAAA!
BBBB!
CCCC!
DDDD!
为什么没有僵局?另外,这是竞争条件的示例,还是此代码是线程安全的?我认为这是有竞争条件的,因为如果task_one
可以在task_two
之前获得M2的锁定,那么一切都会执行(即task_one
将完成,然后允许{{1 }} 开始)。但是,我用相同的结果运行了好几次。另外,如果我关于锁和线程的说法不正确,请纠正我。
答案 0 :(得分:2)
仅仅因为可能发生死锁(确实在发布的代码中可以发生),并不意味着总是会发生 。
就您而言,task_one
恰好在task_two
完全运行之前就完成了。
多线程就像这样:滑。