Singleton* Singleton::instance() {
if (pInstance == 0) {
Lock lock;
if (pInstance == 0) {
Singleton* temp = new Singleton; // initialize to temp
pInstance = temp; // assign temp to pInstance
}
}
假设编译器没有优化冗余临时。线程 A 在并分配并构造了 Singleton 对象,此对象由 temp 指向。现在 A 在那之后被抢占。现在线程 B 获取锁,进入并检查 pInstance 是否为 NULL。它还将创建 Singleton 对象并覆盖现有指针。我想现在有内存泄漏。你有什么意见?完整的来源在这里:代码参考:http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf
No.当 A 被中断时,它拥有锁。因此,B 必须等到 A 释放锁,但随后分配了 pInstance,B 对 null 的第二次检查将失败。
在第11 C++,标准在第6.7段中规定:
这样的变量在控件第一次通过时初始化其声明;这样的变量被认为是在完成其初始化。[...]如果控件进入在初始化变量时并发声明,并发执行应等待初始化完成。
实现不得在执行初始值设定项。
这导致了以下非常简单且线程安全的单例方法实现:
Singleton* Singleton::instance() {
Singleton instance;
return &instance;
}
有关哪些编译器支持此功能的更多详细信息,请参阅此问题。