我正在教自己一些有关并发编程的知识,特别是在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
将完成,然后允许task_two
开始)。但是,我用相同的结果运行了好几次。另外,如果我关于锁和线程的说法不正确,请更正我。
仅由于死锁can发生(确实如此,在发布的代码中确实如此),并不意味着它总是will发生。
就您而言,task_one
恰好在task_two
开始运行之前就完成了。
多线程就是这样:滑。