DCLP (ダブルチェック ロック パターン) について読んでいますが、それが正しいかどうかわかりません。アトミックを使用してロックを作成する場合 ( C++11 で修正された DCLPで説明されているように)、不明な点が 2 つあります。
- 記事のコード:
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 が機能することを確認しています。それが正しいか?
ありがとう!
編集:シングルトンを実装するための質問をしているのではなく、単にフェンスとアトミックの概念とそれが DCLP をどのように修正したかをよりよく理解するために質問していることに注意してください。理論的な質問です。