ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java中安全发布对象

2021-01-04 09:59:11  阅读:171  来源: 互联网

标签:java getInstance instance 对象 安全 线程 单例 public


文章目录

发布对象

发布对象:使一个对象能够被当前范围之外的代码所使用

对象逸出:一种错误的发布。当一个对象还没有构造完成时,就使它被其他线程所见

安全发布对象四种方法

1、 在静态初始化函数中初始化一个对象引用

2、 将对象的引用保存到volatile类型域或者AtomicReference对象中

3、 将对象的引用保存到某个正确构造对象的final类型域中

4 、将对象的引用保存到一个由锁保护的域中

私有构造函数,单例对象,静态工厂方法获取对象

懒汉模式: 单例实例在第一次使用时进行创建(线程不安全)

懒汉模式也可以实现线程安全,给getInstance方法添加synchronized关键字(不推荐,因为性能不好)

双重同步锁单例模式:双重监测机制,在方法内部加synchronized关键字(不是线程安全的)

原因是,创建对象是,分为以下三个步骤:

1、 memory = allocate() 分配对象的内存空间

2、ctorInstance() 初始化对象

3、instance = memory() 设置instance指向刚分配的内存

由于JVM和cpu优化,可能会发生指令重排:

1、 memory = allocate() 分配对象的内存空间

3、 instance = memory() 设置instance指向刚分配的内存

2、 ctorInstance() 初始化对象

当以上面这种指令执行时,线程A执行到3 instance = memory() 设置instance指向刚分配的内存 这一步时,线程B执行if(instance == null)这段代码,此时instance != null,线程B直接return instance,导致对象没有初始化完毕就返回

解决办法就是限制对象创建时进行指令重排,volatile+双重监测机制->禁止指令重排引起非线程安全

饿汉模式: 单例实例在类装载时进行创建(线程安全)

枚举模式: 线程安全

懒汉模式

package com.mmall.concurrency.example.singleton;

import com.mmall.concurrency.annoations.ThreadSafe;

/**
 * 懒汉模式 -》 双重同步锁单例模式
 * 单例实例在第一次使用时进行创建
 */
@ThreadSafe
public class SingletonExample5 {

    // 私有构造函数
    private SingletonExample5() {

    }

    // 1、memory = allocate() 分配对象的内存空间
    // 2、ctorInstance() 初始化对象
    // 3、instance = memory 设置instance指向刚分配的内存

    // 单例对象 volatile + 双重检测机制 -> 禁止指令重排
    private volatile static SingletonExample5 instance = null;

    // 静态的工厂方法
    public static SingletonExample5 getInstance() {
        if (instance == null) { // 双重检测机制        // B
            synchronized (SingletonExample5.class) { // 同步锁
                if (instance == null) {
                    instance = new SingletonExample5(); // A - 3
                }
            }
        }
        return instance;
    }
}

饿汉模式

package com.mmall.concurrency.example.singleton;

import com.mmall.concurrency.annoations.ThreadSafe;

/**
 * 饿汉模式
 * 单例实例在类装载时进行创建
 */
@ThreadSafe
public class SingletonExample6 {

    // 私有构造函数
    private SingletonExample6() {

    }

    // 单例对象
    private static SingletonExample6 instance = null;

    static {
        instance = new SingletonExample6();
    }

    // 静态的工厂方法
    public static SingletonExample6 getInstance() {
        return instance;
    }

    public static void main(String[] args) {
        System.out.println(getInstance().hashCode());
        System.out.println(getInstance().hashCode());
    }
}

枚举模式

package com.mmall.concurrency.example.singleton;

import com.mmall.concurrency.annoations.Recommend;
import com.mmall.concurrency.annoations.ThreadSafe;

/**
 * 枚举模式:最安全
 */
@ThreadSafe
@Recommend
public class SingletonExample7 {

    // 私有构造函数
    private SingletonExample7() {

    }

    public static SingletonExample7 getInstance() {
        return Singleton.INSTANCE.getInstance();
    }

    private enum Singleton {
        INSTANCE;

        private SingletonExample7 singleton;

        // JVM保证这个方法绝对只调用一次
        Singleton() {
            singleton = new SingletonExample7();
        }

        public SingletonExample7 getInstance() {
            return singleton;
        }
    }
}

标签:java,getInstance,instance,对象,安全,线程,单例,public
来源: https://blog.csdn.net/qq_45384482/article/details/112168869

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有