这里讲的线程不安全,主要是在判断是否创建了这个实例的代码块里。楼上很多赞的那个,提到的方法叫双重检查锁定。
问题根源是,instance = new Instance()可以分解成三行伪代码。正常的顺序是分配对象的内存空间->初始化对象->设置instance指向刚分配的内存地址。注意第2.3步会被重排序。这时候instance被分配了内存但是没有初始化。如果这时候有一个线程B来访问,他判断instance!=null后调用这个对象时发现对象没有初始化,就出现bug了~解决方案:1、Instance声明为volatile类型。2、允许重排序,但是重排序不被其他线程看到。
问题根源是,instance = new Instance()可以分解成三行伪代码。正常的顺序是分配对象的内存空间->初始化对象->设置instance指向刚分配的内存地址。注意第2.3步会被重排序。这时候instance被分配了内存但是没有初始化。如果这时候有一个线程B来访问,他判断instance!=null后调用这个对象时发现对象没有初始化,就出现bug了~解决方案:1、Instance声明为volatile类型。2、允许重排序,但是重排序不被其他线程看到。
2017-03-14
public class Singleton2 {
private Singleton2() {}
private static Singleton2 instance;
public static Singleton2 getInstance() {
if (instance == null) {
synchronized (Singleton2.class) {
if (instance == null) {
instance = new Singleton2();}}}
return instance;
}
}
private Singleton2() {}
private static Singleton2 instance;
public static Singleton2 getInstance() {
if (instance == null) {
synchronized (Singleton2.class) {
if (instance == null) {
instance = new Singleton2();}}}
return instance;
}
}
2017-01-09
饿汉模式:类加载的时候便进行了创建...
额...其实是因为static代码块的原因
一个类运行加载进入内存的时候 首先加载static静态代码块
可以搜索一下“考查静态语句块、语句块以及构造函数的执行顺序”
弄懂了就知道饿汉模式了
BTW:上面搜索的东西是一道Java面试题
额...其实是因为static代码块的原因
一个类运行加载进入内存的时候 首先加载static静态代码块
可以搜索一下“考查静态语句块、语句块以及构造函数的执行顺序”
弄懂了就知道饿汉模式了
BTW:上面搜索的东西是一道Java面试题
2017-01-03