C++ C++;双重检查锁定的危险:解决方法?
我正在读一篇关于斯科特·迈尔斯的“双重检查锁定的危险”的论文 作者给出了双重检查锁失败的原因(第3页,第4节)。我在想不用C++11就能解决这个问题的方法。不是我不想使用C++ 11,而是想看看是否可以在不使用STD::Call一次等的情况下解决它。C++ C++;双重检查锁定的危险:解决方法?,c++,c++03,double-checked-locking,C++,C++03,Double Checked Locking,我正在读一篇关于斯科特·迈尔斯的“双重检查锁定的危险”的论文 作者给出了双重检查锁失败的原因(第3页,第4节)。我在想不用C++11就能解决这个问题的方法。不是我不想使用C++ 11,而是想看看是否可以在不使用STD::Call一次等的情况下解决它。 class Singleton { public: static Singleton* instance(); private: static Singleton* pInstance; int someData_; };
class Singleton {
public:
static Singleton* instance();
private:
static Singleton* pInstance;
int someData_;
};
Singleton* Singleton::instance()
{
class SeqAssign{
public:
SeqAssign(Singleton*& pInst, Singleton* pNew):
pInstance(pInst), pNewedInst(pNew){
}
~SeqAssign(){
pInstance = pNewedInst;
}
private:
Singleton*& pInstance;
Singleton* pNewedInst;
};
if (pInstance == 0) { // 1st test
Lock lock;
if (pInstance == 0) { // 2nd test
SeqAssign seq(pInstance, new Singleton);
}
}
return pInstance;
}
Singleton::instance()中的代码能否在多线程环境中工作,因为SeqAssign类调用构造函数和析构函数的顺序是确定的。否。变量
pInstance
是从多个线程访问的。信息技术
是修改过的。代码具有未定义的行为。我不知道是什么
你的东西SeqAssign
就可以了,因为它不会引入任何额外的功能
线程间排序
在标准C++中,没有办法进行双重检查日志记录工作;全部的
大多数解决方案涉及原子变量(可能使用
内联汇编程序)或线程本地存储 解决方法是“不要使用单例”。你是对的,有时候,单例被称为反模式,建议避免它。这里的问题不是单例,而是关于如何使双重检查锁定工作。如果你不想要C++11的东西,不要这样标记问题。我重新标记到
[c++03]
@Ram,这不是我认识的任何专家所做的。几乎普遍的共识是,对于一些特定用途来说,这是一种有用的模式(但它可能会被严重滥用)。实际上,“在进入主要领域之前”有点复杂,因为你经常需要建立事物的顺序,而那些“在主要领域之前”的事物几乎是以随机顺序发生的。我一般都做了两件事:我收集了一系列“要做的事情”的优先级,以在主之前建立正确的排序,并在MIN中提前完成该列表。TLS和原子现在是标准C++的一部分。你可能想把它修改成标准的C++03.James,你能解释一下为什么吗?这里,析构函数调用是确定性的,它必须位于作用域的末尾。C++不能保证RAII的安全性。如果是这样的话,按照同样的逻辑,这应该不起作用吗?@Ram:这不是一个可以观察到的副作用——也就是说,优化器可以自由地内联和移动它。@DeadMG最初的海报问到了非C++11。我应该明确指出,这是我所指的标准,而不仅仅是编译器。全局内存中出现的顺序值不一定是编译器生成的汇编程序中存储指令出现的顺序。硬件现在进行了大量的重新排序,这就是为什么即使关闭所有编译器优化,也需要显式同步。