c++11 - 使用互斥锁的 C++ 程序会给出不可预测的输出。期待一个僵局,但没有得到它
问题描述
我有使用互斥锁进行自学的代码。链接是:https ://baptiste-wicht.com/posts/2012/04/c11-concurrency-tutorial-advanced-locking-and-condition-variables.html
我写了这个例子:main_deadlock.cpp
#include <iostream>
#include <thread>
#include <mutex>
struct Complex {
std::mutex mutex;
int i;
Complex() : i(0) {}
void mul(int x){
std::cout << "mul : before lock_guard" << std::endl;
std::lock_guard<std::mutex> lock(mutex);
std::cout << "mul : after lock_guard, before operation" << std::endl;
i *= x;
std::cout << "mul : after operation" << std::endl;
}
void div(int x){
std::cout << "div : before lock_guard" << std::endl;
std::lock_guard<std::mutex> lock(mutex);
std::cout << "div : after lock_guard, before operation" << std::endl;
i /= x;
std::cout << "div : after operation" << std::endl;
}
void both(int x, int y)
{
std::cout << "both : before lock_guard" << std::endl;
std::lock_guard<std::mutex> lock(mutex);
std::cout << "both : after lock_guard, before mul()" << std::endl;
mul(x);
std::cout << "both : after mul(), before div()" << std::endl;
div(y);
std::cout << "both : after div()" << std::endl;
}
};
int main(){
std::cout << "main : starting" << std::endl;
Complex complex;
std::cout << "main : calling both()" << std::endl;
complex.both(32, 23);
return 0;
}
我希望这段代码在从 both() 调用 mul() 时会出现死锁,因为 both() 已经获取了互斥锁,所以 mul() 应该被阻止。
现在我正在使用: ubuntu 17.10.1 和 g++ (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0 (g++ --version 输出)
如果我使用编译命令:
用户@用户:g++ -o out_deadlock main_deadlock.cpp
我根本没有僵局!
但是如果我使用编译命令:
用户@用户:g++ -std=c++11 -pthread -o out_deadlock main_deadlock.cpp
一切正常 - 意味着我看到了死锁。
你可以解释吗?另外,第一个命令如何使代码编译?我没有“提到” pthreads,也没有提到 -std=c++11 尽管代码使用的是 c++ 11 lib?我希望编译/链接失败?
谢谢。
解决方案
答案是,如果你不编译和链接,-pthread
那么你就没有使用实际的 pthread 锁定函数。
GNU Linux C 库就是这样设置的,这样库就可以调用所有的锁定函数,但是除非它们实际链接到多线程程序中,否则实际上不会发生任何锁定。
推荐阅读
- assembly - 这个汇编程序的堆栈是如何工作的?
- python - 如果数据库包含某个值,则将 x 数量添加到变量(python)
- html - 在月亮上停止 css 关键帧翻转动画,如月相
- tensorflow - 谷歌云 GPU 机器突然重启
- java - 将变量转换为 Big O 中的原始操作吗?
- php - 我无法到达表格的 td 标签
- java - 从 Firebase 数据库中检索计数数据
- python - 除了手动之外,如何在 Matplotlib 中“暂停”、“恢复”和“重置”默认颜色循环?
- php - Apache 2.4 PHP 启动:无法加载动态库 'curl.so'、libcurl.4.dylib
- go - 如何使用 go 获取两位数的当前小时和分钟?