C++指定条件下函数指针赋值调用代码是否线程安全?
结论
这段代码不是线程安全的,即使满足你给出的两个特殊条件也一样。
原因分析
- 首先明确C++标准的基础规则:多个线程在没有同步措施的情况下,同时对同一个非原子变量执行写操作,不管写入的值是否完全相同,都属于「数据竞争」,是明确的未定义行为,程序运行结果没有任何保障。
- 你的代码的竞态场景非常容易复现:
- 初始状态下
pfnSomeFunc为nullptr,两个线程同时调用CalledFromManyThreads - 两个线程都先判断
pfnSomeFunc == nullptr,都得到true的结果,同时进入赋值分支 - 两个线程同时执行
pfnSomeFunc = SomeFuncGetter(),触发对pfnSomeFunc的并发写,直接产生数据竞争
- 初始状态下
- 哪怕
SomeFuncGetter返回的值完全相同也解决不了问题:最坏情况下指针的写入操作可能被拆分为多个CPU指令执行,某个线程可能读到只写了一半的非法指针值,调用pfnSomeFunc()会直接触发崩溃,或者出现其他完全不可预期的行为。
简单的修复方案
你可以直接用C++11及以上标准提供的线程安全静态变量初始化(也叫magic static)来改写,不需要自己加锁也能保证安全:
PFN_SOMEFUNC GetSafeSomeFunc() { static PFN_SOMEFUNC instance = SomeFuncGetter(); return instance; } void CalledFromManyThreads() { GetSafeSomeFunc()(); }
这种写法下,instance的初始化过程会被编译器自动加同步保护,只会执行一次,不存在并发问题。
内容的提问来源于stack exchange,提问作者chaeyk
相关产品推荐
相关产品推荐

