一个典型的单例模式构建对象的双重检查锁如下:

 static Singleton * getSingleObject()
{
if(singleObject==NULL)
{
lock();
if(singleObject==NULL)
{
singleObject = new Singleton();
}
unlock();
}
return singleObject;
}

该代码的逻辑是:getSingleObject()函数获得对象,如果对象不存在则创建,反之则直接返回。考虑到线程安全,创建对象时需要加锁(否则可能多线程同时调用该函数时创建多个对象)。同时为了避免线程每次调用getSingleObject()函数时候都要被锁住等待,减小线程间的开销,使用双重检查锁,即只有对象不存在时才锁住等待。

看起来天衣无缝……

C++在new一个对象时,首先会把指针指向分配的那块空间,然后在初始化该空间。

这样假设线程A执行到new该对象时,分配了指针,但是还未来得及构建那块空间。此时线程B执行getSingleObject()函数,由于指针已经分配所以直接返回该地址(但其实是一块还未初始化的地址),线程B操作该地址,game over。。

一种解决方法,但还是有可能出错:

 class Singleton {
public:
static volatile Singleton* volatile instance();
...
private:
// one more volatile added 加入另一个volatile声明
static volatile Singleton* volatile pInstance;
};
// from the implementation file 实现文件内容如下
volatile Singleton* volatile Singleton::pInstance = ;
volatile Singleton* volatile Singleton::instance() {
if (pInstance == ) {
Lock lock;
if (pInstance == ) {
// one more volatile added 加入另一个volatile声明
volatile Singleton* volatile temp =
new volatile Singleton;
pInstance = temp;
}
}
return pInstance;
}

C++的双重检查锁并不安全(转)的更多相关文章

  1. 单例模式中用volatile和synchronized来满足双重检查锁机制

    背景:我们在实现单例模式的时候往往会忽略掉多线程的情况,就是写的代码在单线程的情况下是没问题的,但是一碰到多个线程的时候,由于代码没写好,就会引发很多问题,而且这些问题都是很隐蔽和很难排查的. 例子1 ...

  2. Java中的双重检查锁(double checked locking)

    最初的代码 在最近的项目中,写出了这样的一段代码 private static SomeClass instance; public SomeClass getInstance() { if (nul ...

  3. 双重检查锁实现单例(java)

    单例类在Java开发者中非常常用,但是它给初级开发者们造成了很多挑战.他们所面对的其中一个关键挑战是,怎样确保单例类的行为是单例?也就是说,无论任何原因,如何防止单例类有多个实例.在整个应用生命周期中 ...

  4. Java基础教程:多线程杂谈——双重检查锁与Volatile

    Java基础教程:多线程杂谈——双重检查锁与Volatile 双重检查锁 有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时程序员可能会采用延迟初始化.但要正确实 ...

  5. 【Java学习笔记】线程安全的单例模式及双重检查锁—个人理解

    搬以前写的博客[2014-12-30 16:04] 在web应用中服务器面临的是大量的访问请求,免不了多线程程序,但是有时候,我们希望在多线程应用中的某一个类只能新建一个对象的时候,就会遇到问题. 首 ...

  6. 对象部分初始化:原理以及验证代码(双重检查锁与volatile相关)

    对象部分初始化:原理以及验证代码(双重检查锁与volatile相关) 对象部分初始化被称为 Partially initialized objects / Partially constructed ...

  7. 为什么双重检查锁模式需要 volatile ?

    双重检查锁定(Double check locked)模式经常会出现在一些框架源码中,目的是为了延迟初始化变量.这个模式还可以用来创建单例.下面来看一个 Spring 中双重检查锁定的例子. 这个例子 ...

  8. 双重检查锁单例模式为什么要用volatile关键字?

    前言 从Java内存模型出发,结合并发编程中的原子性.可见性.有序性三个角度分析volatile所起的作用,并从汇编角度大致说了volatile的原理,说明了该关键字的应用场景:在这补充一点,分析下v ...

  9. 从学习“单例模式”学到的Java知识:双重检查锁和延迟初始化

    一切真是有缘,上午刚刚看完单例模式,还在为其中的代码块同步而兴奋,下午就遇见这篇文章:双重检查锁定与延迟初始化.我一看,文章开头语出惊人,说这是一种错误的优化,我说,难道上午学的东西下午就过时了吗?仔 ...

随机推荐

  1. NSURLSession使用模板和AFNetworking使用模板(REST风格)

    1.NSURLSession使用模板 NSURLSession是苹果ios7后提供的api,用来替换 NSURLConnection会话指的是程序和服务器的通信对象//一.简单会话不可以配合会话(ge ...

  2. box-sizing重置

    html { /*-webkit-box-sizing: border-box; -moz-box-sizing: border-box;*/ box-sizing: border-box; } *, ...

  3. javascript作用域链理解

    执行上下文(Execution context,简称EC)   概念   每当控制器到达ECMAScript可执行代码的时候,就进入了一个执行上下文.   javascript中,EC分为三种:   ...

  4. layer相关

    关闭窗口 var index = parent.layer.getFrameIndex(window.name);parent.layer.close(index);

  5. [AGC016B] Colorful Hats (结论)

    Description 有n个人,每个人都戴着一顶帽子.当然,帽子有不同的颜色. 现在,每个人都告诉你,他看到的所有其他人的帽子共有多少种颜色,请问你有没有符合所有人的描述的情况. Input 第一行 ...

  6. js81:Image对象,几张图像缓存完之后动画显示,form.elements[],document.images[]

    原文发布时间为:2008-11-09 -- 来源于本人的百度文章 [由搬家工具导入] <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tran ...

  7. [LeetCode] Climbing Stairs 斐波那契数列

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  8. 使用layer的iframe层提交表单后,需要关闭当前的iframe层,然后刷新父页面的方法2

    <input type="button" onclick="edit(${it.id?c})" class="layui-btn layui-b ...

  9. 转:C#制作ORM映射学习笔记三 ORM映射实现

    现在开始实现ORM的主体模块,首先需要在项目中新建一个类,命名为DbAccess,然后在项目的引用中添加两个dll,分别是MySql.Data.dll和System.Data.SQLite.dll,这 ...

  10. Educational Codeforces Round 35 B. Two Cakes【枚举/给盘子个数,两份蛋糕块数,最少需要在每个盘子放几块蛋糕保证所有蛋糕块都装下】

    B. Two Cakes time limit per test 1 second memory limit per test 256 megabytes input standard input o ...