复习:DCLP 和 Memory Reordering
本文是对 Jeff Preshing 的 Double Checked Locking Is Fixed in C++ 11 笔记。
0x00 传统实现
因为 synchronization 只需要在实例第一次创建时保证;此后( instance != nullptr
时)都不需要锁来保证 synchronization。
在第一次判断实例为空和上锁之间存在一个 potential race,因此上锁后需要再一次判断实例是否为空。
这也是 double checked 的来由。
所以一个传统但并不100%正确的 DCLP 实现如下:
1 | class Singleton { |
这基本是早起 C++ DCLP 的实现架子。
0x01 问题:内存乱序以及为什么锁帮不了忙
语句
1 | instance = new Singleton(); |
在 C++ 中实际上等效于
1 | tmp = operator new(sizeof(Singleton)); // step 1: allocate memory via operator new |
注意:其中除了分配内存是固定第一步之外,构造对象和赋值内存地址的生成代码顺序是由编译器自己决定。这里的顺序只是一种可能性。