Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
1.instance()
修改点
修改前:instance()函数中使用的是双重校验锁,
修改后:instance()中使用std::call_once替换双重校验所,增加多线程下线程安全性
问题
问题主要出在内存模型和可见性上。在多线程环境中,可能存在指令重排或内存可见性的问题。因此,在第一次检查和初始化之间,另一个线程可能会看到某个对象已经被分配内存但尚未被完全初始化的情况,这可能导致使用未完全初始化的对象,从而产生不确定的行为。
例:首先new一个对象时,分为三个步骤,1分配内存 2构造对象 3返回指针。所以常规顺序是123,但是编译器有时候为了优化会指令重排,导致顺序变成132,这里我们考虑这么一种情况
A线程:new1分配内存并按照指令重拍之后的顺序将2地址返回s_pInstance指针(这时候s_pInstance指针是非空的,但是还没有到达构造构造,此时时间片用完,线程切换)
B线程进入,此时发现s_pInstance是非空的,便直接将s_pInstance返回给调用者,而调用着使用这个没有构造的对象将会发生不可预测的后果
指令重拍原因很多,比如编译器优化或者cpu指令流水线导致
2.exitInstance()
修改前:exitInstance() 函数原本使用mutex的lock()和unlock()
修改后:使用lock_guard替换mutex,避免delete之前存在异常,导致mutex锁无法正确释放