单件可确保在整个程序中只有一个特定类型的对象存在。双检锁是在多线程应用程序中对单件进行初始化的一种常见的有效方法。以下代码将说明这样的实现。
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;
ptr_instance 的读取(第 202 行)特意未用锁进行保护。这样就可以通过检查来确定 Singleton(单件)是否已经在多线程环境中进行有效实例化。请注意,第 202 行的读取与第 212 行的写入之间存在对变量 ptr_instance 的数据争用,但程序可正常工作。不过,编写允许数据争用的正确程序时,需要格外小心。例如,在以上双检锁定代码中,第 209 行中对 memory_barrier() 的调用用来确保线程不会看到 ptr_instance 为非空,直至构造 Singleton(单件)的所有写入已完成。