在C ++ 11中经过双重检查的锁定模式?

| C ++ 11的新机器模型允许多处理器系统可靠地工作。重组指令。 正如Meyers和Alexandrescu指出的那样,“简单”双重检查锁定模式实现在C ++ 03中并不安全
Singleton* Singleton::instance() {
  if (pInstance == 0) { // 1st test
    Lock lock;
    if (pInstance == 0) { // 2nd test
      pInstance = new Singleton;
    }
  }
  return pInstance;
}
他们在文章中表明,无论您是一名程序员做什么,在C ++ 03中,编译器都具有很大的自由度:允许对指令进行重新排序,而不能确保最终只能得到一个指令。
Singleton
的实例。 我的问题是: 现在,新C ++ 11机器模型的限制/定义是否限制了指令的顺序,即上述代码始终可以与C ++ 11编译器一起使用? 使用新的库工具(而不是此处的模拟
Lock
)时,此Singleton模式的安全C ++ 11-实施现在看起来如何?     
已邀请:
如果
pInstance
是常规指针,则代码具有潜在的数据竞争-不能保证对指针(或任何内置类型)的操作是原子性的(编辑:或顺序良好) 如果
pInstance
std::atomic<Singleton*>
,而
Lock
在内部使用
std::mutex
实现同步(例如,如果
Lock
实际上是
std::lock_guard<std::mutex>
),则代码应无数据争用。 请注意,您既需要显式锁定又需要原子“ 3”来实现正确的同步。     
由于现在保证静态变量初始化是线程安全的,因此Meyer的单例应该是线程安全的。
Singleton* Singleton::instance() {
  static Singleton _instance;
  return &_instance;
}
现在,您需要解决一个主要问题:您的代码中有一个Singleton。 编辑:根据下面我的评论:与其他实现相比,此实现有一个主要缺点。如果编译器不支持此功能会怎样?编译器将发出线程不安全的代码,甚至不会发出警告。如果编译器不支持新接口,则其他带有锁的解决方案甚至都不会编译。这可能是不依赖此功能的一个很好的理由,即使对于单例用户而言也是如此。     
C ++ 11不会更改双重检查锁定的实现的含义。如果要进行双重检查的锁定工作,则需要建立合适的内存屏障/栅栏。     

要回复问题请先登录注册