我正在阅读有关 DCLP(双重检查锁定模式)的信息,但我不确定我是否正确。当使用原子来创建锁时(如DCLP 中所述,在 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。这是一个理论问题。