【发布时间】:2015-06-02 04:58:19
【问题描述】:
我正在阅读有关 DCLP(双重检查锁定模式)的信息,但我不确定我是否正确。在使用原子创建锁时(如DCLP fixed in C++11 中所述),有两点不清楚:
- 在文章代码中:
std::atomic<Singleton*> Singleton::m_instance; std::mutex Singleton::m_mutex; Singleton* Singleton::getInstance() { Singleton* tmp = m_instance.load(std::memory_order_acquire); if (tmp == nullptr) { std::lock_guard<std::mutex> lock(m_mutex); tmp = m_instance.load(std::memory_order_relaxed); if (tmp == nullptr) { tmp = new Singleton; m_instance.store(tmp, std::memory_order_release); } } return tmp; }
如果我在“load()”中获取栅栏,但 tmp 不是 nullptr,我只是返回,会发生什么情况?我们不应该说明 CPU 可以在哪里“释放围栏”吗?
如果不需要释放栅栏,那我们为什么要获取和释放?有什么区别?
Surly 我错过了一些基本的东西......
- 如果我正确理解了这篇文章,那么这也是实现 DCLP 的正确方法吗?
Singleton* Singleton::m_instance = null; std::atomic<bool> Singleton::is_first; // init to false std::mutex Singleton::m_mutex; Singleton* Singleton::getInstance() { bool tmp = is_first.load(std::memory_order_acquire); if (tmp == false) { std::lock_guard<std::mutex> lock(m_mutex); tmp = is_first.load(std::memory_order_relaxed); if (tmp == false) { // can place any code that will run exactly once! m_instance = new Singleton; // store back the tmp atomically is_first.store(tmp, std::memory_order_release); } } return m_instance; }
换句话说,我没有查看实例,而是使用原子布尔值来确保 DCLP 工作,并且第二个 tmp 内的任何内容都必须同步并运行一次。对吗?
谢谢!
编辑:请注意,我不是在问实现单例的问题,而只是为了更好地理解栅栏和原子的概念以及它如何修复 DCLP。这是一个理论问题。
【问题讨论】:
-
您在修改后的版本中返回布尔值而不是
Singleton*... -
您不会“获得栅栏”或“释放栅栏”。栅栏具有获取或释放语义。
标签: c++ multithreading c++11 double-checked-locking