除非与pthreads相关联,否则没有死锁?

时间:2017-05-06 23:35:23

标签: c++ linker pthreads mutex compiler-optimization

为什么创建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;
}

据我所知,没有线程库,您实际上并不需要互斥功能,但编译器是否知道链接的库?它可以根据它进行优化吗?

1 个答案:

答案 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相关联。