シングルトンは、特定の種類のオブジェクトが、プログラム全体で 1 つしか存在しないようにします。二重検査されたロックは、マルチスレッドアプリケーションでシングルトンを初期化する一般的で効率的な方法です。次のコードは、この実装方法を示します。
100 class Singleton { 101 public: 102 static Singleton* instance(); 103 ... 104 private: 105 static Singleton* ptr_instance; 106 }; ... 200 Singleton* Singleton::ptr_instance = 0; ... 300 Singleton* Singleton::instance() { 301 Singleton *tmp = ptr_instance; 302 memory_barrier(); 303 if (tmp == NULL) { 304 Lock(); 305 if (ptr_instance == NULL) { 306 tmp = new Singleton; 307 memory_barrier(); 308 ptr_instance = tmp; 309 } 310 Unlock(); 311 } 312 return tmp; 313 }
ptr_instance の読み取り (行 301) は、ロックによって意図的に保護されていません。このため、マルチスレッド環境でシングルトンがすでにインスタンス化されているかどうかを判別するチェックが効率的になります。変数 ptr_instance の行 301 での読み取りと行 308 での書き込みとの間でデータの競合があるが、プログラムは正しく動作することに注意してください。ただし、データの競合を許可する正しいプログラムを作成すると、余分な注意が必要になります。たとえば、前述の二重検査されたロックコードでは、シングルトンおよび ptr_instance を適切な順序で設定および読み取りできるように、行 302 および 307 での memory_barrier() の呼び出しが使用されます。この結果、すべてのスレッドは連続してこれらを読み取ります。このプログラムテクニックは、メモリーバリアーを使用しない場合には機能しません。