Oracle® Solaris Studio 12.4: スレッドアナライザユーザーズガイド

印刷ビューの終了

更新: 2014 年 12 月
 
 

二重検査されたロックを使用したプログラム

シングルトンは、特定の種類のオブジェクトが、プログラム全体で 1 つしか存在しないようにします。二重検査されたロックは、マルチスレッドアプリケーションでシングルトンを初期化する一般的で効率的な方法です。次のコードは、この実装方法を示します。

100 class Singleton {
101     public:
102     static Singleton* instance();
103     ...
104     private:
105     static Singleton* ptr_instance;
106 };
107
108 Singleton* Singleton::ptr_instance = 0;
...

200 Singleton* Singleton::instance() {
201     Singleton *tmp;
202     if (ptr_instance == 0) {
203         Lock();
204         if (ptr_instance == 0) {
205             tmp = new Singleton;
206
207             /* Make sure that all writes used to construct new
208                Singleton have been completed. */
209             memory_barrier();
210
211             /* Update ptr_instance to point to new Singleton. */
212             ptr_instance = tmp;
213
214         }
215         Unlock();
216     }
217     return ptr_instance;

行 202 の ptr_instance の読み取りは、ロックによって意図的に保護されていません。このため、マルチスレッド環境で Singleton がすでにインスタンス化されているかどうかを判別するチェックが効率的になります。変数 ptr_instance の行 202 での読み取りと行 212 での書き込みとの間でデータの競合があるが、プログラムは正しく動作することに注意してください。ただし、データの競合を許可する正しいプログラムを作成すると、余分な注意が必要になります。たとえば、上記の二重検査されたロックのコードで、行 209 での memory_barrier() の呼び出しは、Singleton を構築するためのすべての書き込みが完了するまで、ptr_instance がスレッドによって非 NULL として認識されないようにするために使用されます。