为什么创建std :: mutex死锁实际上不会导致死锁,除非程序链接到pthreads?
以下将与pthreads库链接时死锁,如果没有链接到pthreads则不会死锁。在gcc和clang上测试。
// clang++ main.cpp -std=c++14 -lpthread
#include <mutex>
int main() {
std::mutex mtx;
mtx.lock();
mtx.lock();
return 0;
}
据我所知,没有线程库,您实际上并不需要互斥功能,但编译器是否知道链接的库?它可以根据它进行优化吗?
答案 0 :(得分:3)
以下将与pthreads库链接时死锁,如果没有链接pthreads,则不会死锁。
那是因为std::mutex::lock
的默认实现 nothing 。
编译器是否知道链接的库?
否:编译器只需调用std::mutex::lock
并将mtx
的地址传递给它。它是该函数的实现,其行为方式不同。
<强>更新强>
为了澄清,实现能够根据库是否已链接而自行更改?通过宏?
当编译器完成编译时,宏预处理也完成,并且不会有任何进一步的效果。
也许最好的证明。假设你有:
int main() { return foo(); }
你能说出上述程序的执行结果是什么吗?不,你不能,因为你不知道foo
做了什么。
现在假设我编译了以下内容:
// foo.c
int foo() { return 0; }
gcc -c foo.c && ar ruv libfoo.a foo.o
gcc main.o -L. -lfoo
现在您可以告诉程序将以0
返回代码退出。
现在假设我还编译了以下内容:
// bar.c
int foo() { abort(); }
gcc -c bar.c && ar ruv libbar.a bar.o
最后,我像这样链接相同的未修改的 main.o
:
gcc main.o -L. -lbar -lfoo
你能告诉结果程序会做什么吗?
你可以:它会死于SIGABRT
并产生核心转储。
请注意main.o
没有更改,只有main.o
链接的库已更改。
这与导致原始程序的行为方式完全相同,具体取决于它是否与libpthread
相关联。