linux - 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_lock
and的 dummy 实现pthread_mutex_unlock
什么都不做。
在 的情况下pthread_self
,虚拟实现必须返回一些值,并且该值为零。(POSIX 不保留任何pthread_t
值来指示失败或其他极端情况,所以这很好。)当与 链接时-lpthread
,使用非虚拟实现,它返回一个指向内部线程数据结构的指针(转换为unsigned long
),并且这个value 永远不会为零,即使对于初始(主)线程也是如此。这就是为什么-lpthread
链接器命令行上的存在很重要。
其他人无法重现此行为,因为他们使用的是非 glibc 系统或更新版本的 glibc。现在,glibc 只有一个线程库实现,最初是 NPTL,它与 glibc 的其余部分紧密集成。这意味着不再需要转发器,并且在 glibc 2.27 中,pthread_self
永远不会返回零。顺便说一句,这个更改有助于实现,其中:std::thread
返回的值零表示没有 ID,而不是线程是主线程(如在未加载的旧 glibc 版本中)。因此需要一个 kludge 来支持 glibc 2.26 及更早版本。get_id()
std::thread::id{}
libpthread
libstdc++
转发器还有另一个好处:它们可以优化性能,而不仅仅是为了(如果未链接pthread_mutex_lock
则什么都不做)。libpthread
某些libpthread
功能无需-lpthread
. 这意味着应用程序可以使用同步,并且它们可以检查符号的存在,例如pthread_create
或pthread_cancel
(使用弱符号引用)。如果这些弱符号是未定义的,那么很明显该进程必须是单线程的,因为libpthread
不存在,这意味着不能创建线程。在这种情况下,例如,没有必要使用原子指令进行引用计数。(std::shared_ptr
在libstdc++
使用这样的优化。)但是这种优化越来越无效,因为大多数过程映像都包含libpthread
这些天:某些库需要它,因此它作为间接依赖项加载。这意味着转发器也失去了其他目的,它们正逐渐从 glibc 中删除。(添加了glibc 2.32__libc_single_threaded
以启用单线程优化,即使libpthread
已加载,但尚未创建线程。)
推荐阅读
- python - 使用大量列表优化 for 循环
- eventsource - EventSource.js 未导出 NativeEventSource、EventSourcePolyfill
- javascript - Socket.IO Ping随机网站查看在线状态
- wordpress - 使用简单查询的 wp_query 中的无限循环
- onnx - 如何将 ONNX 网络(由 MatLab 生成)转换为 caffemodel?
- python - 如何在 Excel 文件中导出具有多个值的字典
- javascript - svg 填充的平滑动画
- rest - 无法通过 cron 选项卡进行 resty.v2 POST 调用
- java - 将我的 Cordapps 升级到 v4.1 后,我的 Junits 工作正常,但在服务器上出现错误,如何解决这个问题?
- javascript - Redux-ORM,带有 ReactJS 选择器没有返回值