因此,在有了C++11后我们就可以正确的跨平台的实现DCL模式了,代码如下:
1 atomic<Widget*> Widget::pInstance{ nullptr };
2 Widget* Widget::Instance() {
3 if (pInstance == nullptr) {
4 lock_guard<mutex> lock{ mutW };
5 if (pInstance == nullptr) {
6 pInstance = new Widget();
7 }
8 }
9 return pInstance;
10 }
C++11中的atomic类的默认memory_order_seq_cst保证了3、6行代码的正确同步,由于上面的atomic需要一些性能上的损失,因此我们可以写一个优化的版本:
1 atomic<Widget*> Widget::pInstance{ nullptr };
2 Widget* Widget::Instance() {
3 Widget* p = pInstance;
4 if (p == nullptr) {
5 lock_guard<mutex> lock{ mutW };
6 if ((p = pInstance) == nullptr) {
7 pInstance = p = new Widget();
8 }
9 }
10 return p;
11 }
但是,C++委员会考虑到单例模式的广泛应用,所以提供了一个更加方便的组件来完成相同的功能:
1 static unique_ptr<widget> widget::instance;
2 static std::once_flag widget::create;
3 widget& widget::get_instance() {
4 std::call_once(create, [=]{ instance = make_unique<widget>(); });
5 return instance;
6 }
可以看出上面的代码相比较之前的示例代码来说已经相当的简洁了,但是!!!有是但是!!!!在C++memory model中对static local variable,说道:The initialization of such a variable is defined to occur the first time control passes through its declaration; for multiple threads calling the function, this means there’s the potential for a race condition to define first.因此,我们将会得到一份最简洁也是效率最高的单例模式的C++11实现:
1 widget& widget::get_instance() {
2 static widget instance;
3 return instance;
4 }
用Herb Sutter的话来说这份代码实现是“Best of All”的。