pthread_self返回一个大整数或0,这取决于libpthread是否存在

问题描述

#include <pthread.h>
#include <iostream>
 int main(){
     std::cout<<pthread_self()<<std::endl;
}

使用命令g++ 1.cpp -o 1进行编译并执行后,程序输出为0,如果使用命令g++ 1.cpp -o 1 -lpthread进行编译,则输出为140062699310912之类的大数字。

我不明白为什么。

# g++ 1.cpp -o 1 && ./1
0
# g++ 1.cpp -o 1 -lpthread && ./1
140268785461056

解决方法

POSIX标准未指定pthread_t对应的实际类型。在glibc中,它是unsigned long int,这就是C ++流可以打印其值的原因。 (这不是便携式的。)

为什么pthread_self返回零,但仅当-lpthread链接时返回零?

从历史上看,glibc支持两种不同的线程库实现,即LinuxThreads和NPTL。一些核心libpthread函数在glibc本身中具有存根,如果已加载存根,则存根会转发到实际的实现;如果进程中没有线程库,则存根会执行一些虚拟的回退操作。例如,pthread_mutex_lockpthread_mutex_unlock的虚拟实现什么都不做。

对于pthread_self,虚拟实现必须返回 some 值,并且该值为零。 (POSIX不会保留任何pthread_t值来指示故障或其他极端情况,因此很好。)与-lpthread链接时,使用非虚拟实现,该实现返回指向内部的指针。线程数据结构(转换为unsigned long),并且该值永远不会为零,即使对于初始(主)线程也是如此。这就是为什么链接器命令行上-lpthread的存在很重要的原因。

其他人无法重现此行为,因为他们正在使用非glibc系统或更新的glibc版本。如今,只有一种针对glibc的线程库实现,它始于NPTL,并且与其余glibc紧密集成。这意味着不再需要转发器,在glibc 2.27中,pthread_self never returns zero。顺便说一句,此更改有助于实现std::thread,其中get_id()返回的值为零:std::thread::id{}表示没有ID,而不是线程是主线程(如较早的glibc未加载libpthread的版本)。 libstdc++因此需要支持glibc 2.26和更早版本。

转发器还有另一个好处:它们不仅可以针对pthread_mutex_lock进行性能优化,而且还可以优化性能(如果未链接libpthread则不执行任何操作)。如果没有libpthread,则某些-lpthread功能可用。这意味着应用程序可以使用同步,并且可以检查符号pthread_createpthread_cancel等符号的存在(使用弱符号引用)。如果未定义这些弱符号,则很明显该进程必须是单线程的,因为libpthread不存在,这意味着无法创建线程。在这种情况下,例如,不必使用原子指令进行引用计数。 (std::shared_ptr中的libstdc++使用了这样的优化。)但是这种优化的效率越来越低,因为如今大多数过程映像都包含libpthread:某些库需要它,因此它被作为间接依赖项加载。 。这意味着转发器也失去了这个其他目的,它们正逐渐从glibc中删除。 (添加了__libc_single_threaded的glibc 2.32启用了单线程优化,即使加载了libpthread却没有创建线程。)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...