java的单例模式,为什么需要volatile

目前看了java并发的书,记录一下。对于java的单例模式,正确的代码应该为:

public class TestInstance {
    private volatile static TestInstance instance;
    public static TestInstance getInstance() { //1
        if (instance == null) {                  //2
            synchronized (TestInstance.class) {//3
                if (instance == null) { //4
                    instance = new TestInstance();//5
                }
            }
        }
        return instance;//6
    }
}

  

以前不了解为什么需要volatile关键字,后来发现在并发情况下,如果没有volatile关键字,在第5行会出现问题

对于第5行

instance = new TestInstance();

可以分解为3行伪代码

1 memory=allocate();// 分配内存 相当于c的malloc

2 ctorInstanc(memory) //初始化对象

3 instance=memory //设置instance指向刚分配的地址

上面的代码在编译器运行时,可能会出现重排序 从1-2-3 排序为1-3-2

如此在多线程下就会出现问题

例如现在有2个线程A,B

线程A在执行第5行代码时,B线程进来,而此时A执行了 1和3,没有执行2,此时B线程判断instance不为null 直接返回一个未初始化的对象,就会出现问题

而用了volatile,上面的重排序就会在多线程环境中禁止,不会出现上述问题。

时间: 2024-10-03 20:14:52

java的单例模式,为什么需要volatile的相关文章

Java设计模式の单例模式

-------------------------------------------------- 目录 1.定义 2.常见的集中单例实现 a.饿汉式,线程安全 但效率比较低 b.单例模式的实现:饱汉式,非线程安全 c.饱汉式,线程安全简单实现 d.线程安全 并且效率高  单例模式最优方案 3.总结 a.使用枚举的单例模式 b.使用枚举,static处调用,初始化一次 -------------------------------------------------- 1.定义 确保一个类只有

Java 设计模式 单例模式(Singleton) [ 转载 ]

Java 设计模式 单例模式(Singleton) [ 转载 ] 转载请注明出处:http://cantellow.iteye.com/blog/838473 前言 懒汉:调用时才创建对象 饿汉:类初始化时就创建对象 第一种(懒汉,线程不安全): 1 public class Singleton { 2 private static Singleton instance; 3 private Singleton (){} 4 5 public static Singleton getInstan

java 实现单例模式

public class Singleton { private static Singleton intance; private Singleton() {} public static Singleton getInstance() { /* * 一开始多线程进来,遇到锁,一个线程进去,是为空,new对象: 后续线程进入,不为空,不操作:最后直接返回 * 对象不为空,再有多个线程进入该函数,不为空,不执行加锁操作,直接返回 */ if (intance == null) { synchro

JAVA实现单例模式的四种方法和一些特点

JAVA实现单例模式的四种方法和一些特点,需要的朋友可以参考一下 一.饿汉式单例类 复制代码 代码如下: public class Singleton  {      private Singleton(){ } private static Singleton instance = new Singleton(); private static Singleton getInstance(){          return instance;      }  } 特点:饿汉式提前实例化,没有

【转】Java并发中正确使用volatile

Java并发中正确使用volatile 原文链接 http://ifeve.com/how-to-use-volatile/ 作者:一粟   整理和翻译自Twitter实时搜索的PPT 前几天并发编程群里有同学对volatile的用法提出了疑问,刚好我记得Twitter有关实时搜索的这个PPT对这个问题解释的很清晰并有一个实际的应用场景,于是周末把这个问题摘录了一些和并发相关的内容如下: 并发 – 定义 悲观锁 – Pressimistic locking 一个线性在执行一个操作时持有对一个资源

Java中关于原子操作和volatile关键字

Java中关于原子操作和volatile关键字 第一种:采用同步synchronized解决,这样虽然解决了问题,但是也降低了系统的性能. 第二种:采用原子性数据Atomic变量,这是从JDK1.5开始才存在的针对原子性的解决方案,这种方案也是目前比较好的解决方案了.

全面理解Java内存模型(JMM)及volatile关键字(转)

原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoader) 深入理解Java并发之synchronized实现原理 Java并发编程-无锁CAS与Unsafe类及其并发包Atomic 深入理解Java内存模型(JMM)及volatile关键字 剖析基于并发AQS的重入锁(Reetr

Java并发编程之验证volatile不能保证原子性

通过系列文章的学习,凯哥已经介绍了volatile的三大特性.1:保证可见性 2:不保证原子性 3:保证顺序.那么怎么来验证可见性呢?本文凯哥(凯哥Java:kaigejava)将通过代码演示来证明为什么说volatile不能够保证共享变量的原子性操作. 我们来举个现实生活中的例子: 中午去食堂打饭,假设你非常非常的饥饿,需要一荤两素再加一份米饭.如果食堂打饭的阿姨再给你打一个菜的时候,被其他人打断了,给其他人打饭,然后再回过头给你打饭.你选一荤两素再加一份米饭打完的过程被打断了四次耗时30分钟

Java懒汉式单例模式详解

单例模式最常见的有两种,饿汉式和懒汉式两种.本文先简单说一下懒汉式单例,再着重叙述饿汉式单例,饿汉式单例是本文的叙述重点. 懒汉式的优点是:写起来比较简单,而且不存在多线程同步问题,避免了synchronized所造成的性能问题:缺点是:初始化类的时候就需要构造实例,(即便你还没有用到这个实例),因此在某些特定条件下会耗费内存.懒汉式的写法如下: 1 /** 2 * 懒汉式单例 3 * @author James Chong 4 * 5 */ 6 public class SingleTon {