7 c++ concurrency race-condition c++11
以下是来自http://www.ibm.com/developerworks/java/library/j-dcl/index.html的Java示例问题
public static Singleton getInstance()
{
if (instance == null) //#4
{
synchronized(Singleton.class) { //#1
if (instance == null) //#2
instance = new Singleton(); //#3
}
}
return instance;
}
Run Code Online (Sandbox Code Playgroud)
这似乎不安全,因为#3可以在执行构造函数之前将实例设置为非null,因此当另一个线程检查#4上的实例时,它将不为null并返回一个尚未正确构造的实例.
显然使用函数变量不会有帮助,因为它可能被优化或者只是在我们不希望它时将值设置为实例的方式执行.
我认为不是最简单的方法是有一个函数,new Singleton();所以在将它分配给实例之前完成它.现在问题是如何告诉C++一个函数不应该是内联的?我认为 Singleton* make_singleton() volatile应该这样做,但我很肯定我错了.
R. *_*des 25
我会暂时忽略单例位并假设你需要这个用于延迟初始化而不是像单身人士那样愚蠢的东西.
我建议忘记双重检查锁定.C++以这种形式为这种情况提供了一个非常有用的工具std::call_once,所以使用它.
template <typename T>
struct lazy {
public:
// needs constraining to prevent from doing copies
// see: http://flamingdangerzone.com/cxx11/2012/06/05/is_related.html
template <typename Fun>
explicit lazy(Fun&& fun) : fun(std::forward<Fun>(fun)) {}
T& get() const {
std::call_once(flag, [this] { ptr.reset(fun()); });
return *ptr;
}
// more stuff like op* and op->, implemented in terms of get()
private:
std::once_flag flag;
std::unique_ptr<T> ptr;
std::function<T*()> fun;
};
// --- usage ---
lazy<foo> x([] { return new foo; });
Run Code Online (Sandbox Code Playgroud)