解开C++之call_once的神秘面纱:记一个有意思的问题笔记( 二 )


函数返回 __gthread_active_ptr != 0,即如果该指针非空,则表明线程已激活(从指针命名上猜的) 。
所以该函数用于指示线程是否被激活 。不明白?我们继续看__gthrw___pthread_key_create的定义 。
11405 static __typeof(pthread_key_create) __gthrw___pthread_key_create __attribute__ ((__weakref__("__pthread_key_create")));通过 attribute((weakref("__pthread_key_create"))),将 __gthrw___pthread_key_create 弱引用到 __pthread_key_create 。
弱引用是一种机制,允许在链接过程中,如果存在 __pthread_key_create 的定义,则使用它 。但如果找不到 __pthread_key_create,则允许 __gthrw___pthread_key_create 仍然存在,只不过它将保持为空或未定义状态 。
这里大致就明白了,总结一下 , call_once内部实现中要找一个__pthread_key_create定义,如果不存在则返回空,即我们调试的时的指针给了0 , 从而引起异常 。__pthread_key_create函数很明显是线程函数 。好,那我们在代码中加上该函数调用试试看 。在main开始增加如下:
int main(){pthread_key_t key;pthread_key_create(&key, NULL);Init();编译运行:

解开C++之call_once的神秘面纱:记一个有意思的问题笔记

文章插图
达到预期效果了!
所以整体分析一下,在 call_once 的内部实现中,检测是否支持 __pthread_key_create 可能是为了确保在使用 call_once 进行线程同步时,能够利用线程特定数据键来管理状态或资源,确保其正确性和性能 。如果当前环境不支持 __pthread_key_create,那么在多线程环境下可能无法有效地管理线程特定的状态信息 。
因此 , 检测是否支持 __pthread_key_create 可能是 call_once 实现中的一种策略,用于在可能的情况下提供更好的线程安全性和性能 。如果当前环境不支持这个特定的功能,可能会采用其他方式来实现 call_once,或者简化其行为以确保程序在这样的环境中仍能正确运行,尽管可能会牺牲一些特定的功能或性能 。
我尝试不使用__pthread_key_create,随便调用一个pthread库的api,比如pthread_create,或者pthread_mutex_init , 调用可以全部传递空指针,结果依然是可以达到预期的 。所以验证也说明call_once内部通过弱引用库函数来检测当前是否支持多线程 , 如果不支持则抛出异常,所以使用前提必须是多线程环境 。
总结call_once 的魅力与注意事项:
std::call_once 提供了一种简单而又强大的多线程同步方式 , 但在使用时也需注意一些细节 。比如一定要确保程序是多线程调用,如果有多线程自然还要确保线程安全,避免潜在的死锁和竞态条件问题登 。




推荐阅读