前言:
上节中,我们分析了要解决线程重排序的问题,找了两种解决方案,第一种方案上节已经实现,那么我们这节就来实现第二种解决方案。
1、不允许2、3进行重排序,加入了volatile关键字.
2、允许一个线程进行重排序,但不允许另外线程看到他的重排序。
大家有没有想到用静态内部类解决呢?那么我们先了解一下它吧!
1、内部静态类解决原理:如下图1
图一
* jvm在类的初始化阶段,也就是class被加载后,也就是被线程使用之前,都是类的初始化阶段,在这个阶段会执行类的初始化。
* 在执行类的初始化期间呢,jvm会获取一个锁,这个锁可以同步多个线程对一个类的初始化,也就是绿色的部分,基于这个特性,
* 我们可以实现基于静态内部类的、并且是线程安全的延迟初始化方案。
现在我们知道了静态内部类可以不允许另外线程看到他的重排序,是利用了静态内部类具有线程安全的延迟方案的特性。
2、线程安全的延迟方案的特性的扩展
根据java的语言规范,假设有一个类,为A,则一个有五种方案都可以有线程安全的延迟方案的特性。
A类会立刻被初始化的5种情况
* 1、A类型的实例被创建。
* 2、A类中声名的一个静态方法被调用。
* 3、A类中声名的一个静态成员被赋值。
* 4、A类中声名的一个静态成员被使用,并且静态成员不是一个常量成员。
* 5、A类如果是一个顶级类,在类中嵌套的有断言语句,这种情况A类也会被立刻初始化。
* 满足以上某一条件,就会立刻初始化。
3、不允许另外线程看到他的重排序的代码
public class StaticInnerClassSingleton { private static class InnerClass { private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton(); } public static StaticInnerClassSingleton getInstance(){ return InnerClass.staticInnerClassSingleton; } }
结束!