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
答案 0 :(得分:1)
没有。当A被打断时,它会拥有锁。因此B必须等到A释放锁定,但是然后分配pInstance并且B的第二次检查为空将失败。
答案 1 :(得分:1)
在C ++ 11中,该标准在第6.7段中规定:
这个变量在控件第一次通过时被初始化 它的声明;这样的变量被认为是初始化的 完成初始化。 [...]如果控制进入 在变量初始化的同时声明, 并发执行应等待初始化完成。
实现不得在执行时引入任何死锁 初始化器。
这导致以下非常简单且线程安全的单例方法实现:
Singleton* Singleton::instance() {
Singleton instance;
return &instance;
}
有关哪些编译器支持此功能的详细信息,请参阅this question。