前言:
目前你们对“懒汉模式线程安全吗”都比较关切,你们都想要知道一些“懒汉模式线程安全吗”的相关资讯。那么小编在网络上汇集了一些有关“懒汉模式线程安全吗””的相关资讯,希望看官们能喜欢,兄弟们快快来了解一下吧!一、饿汉式
/**
* 单例模式:饿汉式
* 类加载时创建类的实例,没吃饱早些吃饱
*/
public class Singleton
{
//1.将构造方法私有不允许外部new对象
private Singleton()
{
}
//2.创建类的唯一实例
private static Singleton singleton = new Singleton();
//3.提供一个获取实例的方法
public static Singleton getInstance()
{
return singleton;
}
}
二、懒汉式
/**
* 懒汉式
* 类加载时并不会常见实例,当用户获取时,如果实例为空创建实例
*/
public class Singleton2
{
//1.将构造函数私有,不允许外部创建
private Singleton2()
{
}
//2.声明类的唯一实例
private static Singleton2 instance;
//3.提供一个实例获取的方法
public Singleton2 getInstance()
{
if (instance == null)
{
instance = new Singleton2();
}
return instance;
}
}
三、懒汉式的线程安全解决方法
public class Singleton3
{
//1.将构造函数私有,不允许外部创建
private Singleton3()
{
}
//2.声明类的唯一实例
private static volatile Singleton3 instance;////第二层锁,volatile关键字禁止指令重排
//3.提供一个实例获取的方法
public Singleton3 getInstance()
{
if (instance == null)
{
synchronized (Singleton3.class)//第一层锁,保证只有一个线程进入
{
//双重检查,防止多个线程同时进入第一层检查(因单例模式只允许存在一个对象,故在创建对象之前无引用指向对象,所有线程均可进入第一层检查)
//当某一线程获得锁创建一个Singleton对象时,即已有引用指向对象,singleton不为空,从而保证只会创建一个对象
//假设没有第二层检查,那么第一个线程创建完对象释放锁后,后面进入对象也会创建对象,会产生多个对象
if (instance == null)//第二层检查
{
//volatile关键字作用为禁止指令重排,保证返回Singleton对象一定在创建对象后
//singleton=new Singleton语句为非原子性,实际上会执行以下内容:
//(1)在堆上开辟空间;(2)初始化实例;(3)引用指向对象
//假设以上三个内容为三条单独指令,因指令重排可能会导致执行顺序为1->3->2
// (正常为1->2->3),当单例模式中存在普通变量需要在构造方法中进行初始化操作时,
// 单线程情况下,顺序重排没有影响;但在多线程情况下,
// 假如线程1执行singleton=new Singleton()语句时先1再3,
// 由于系统调度线程2的原因没来得及执行步骤2,
// 但此时已有引用指向对象也就是singleton!=null,
// 故线程2在第一次检查时不满足条件直接返回singleton,
// 此时singleton为null(即str值为null)
//volatile关键字可保证singleton=new Singleton()语句执行顺序为123,
// 因其为非原子性依旧可能存在系统调度问题(即执行步骤时被打断),
// 但能确保的是只要singleton!=0,就表明一定执行了属性初始化操作;
// 而若在步骤3之前被打断,此时singleton依旧为null,
// 其他线程可进入第一层检查向下执行创建对象
instance = new Singleton3();
}
}
}
return instance;
}
}