时时彩平台一旦发生了重排序操作

作者: 时时彩平台-编程  发布:2019-10-06

书接上回,还是先把代码再贴一次。

public class LazySingleton { private static volatile LazySingleton instance; private LazySingleton() {} public static LazySingleton getInstance() { if (instance == null) { synchronized(LazySingleton.class){ if (instance == null) { instance = new LazySingleton(); } } } return instance; }}

关键之处还是在声明instance变量时的volatile关键字。因为咋看起来,如果没有这个volatile似乎程序逻辑上也没有什么漏洞。但是,由于instance = new LazySingleton()的操作并不是原子的,而是按以下步骤执行:

  1. 为新对象分配内存空间;
  2. 构造并初始化对象;
  3. 把instance指向步骤1中分配的内存空间。

除此之外,Java运行时环境的JIT编译器会做指令重排序操作,即生成的机器指令与字节码指令顺序不一致。在单线程条件下,即使是步骤2、3发生了重排序,可以保证最终结果保证一致,也就是instance指向来初始化后的对象。而在并发场景下,一旦发生了重排序操作,就有可能出现instance指向了步骤1分配的内存,单尚未完成步骤2的初始化。

此时就轮到『volatile』闪亮登场了。Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

如果希望对java的重排序有更多了解,可以先读一下这篇文章。

虽然已经提供了很多种的单例实现方法,但是最简洁的莫过于使用枚举来实现了。

public enum EnumSingleton { INSTANCE; public void Method() {}}

不仅代码简洁,而且JVM来保证了其线程安全,并且无偿地提供了序列化机制,绝对防止多次实例化,是一种高效安全的单例模式的实现。

但是这种写法我是很少使用的,纯属个人习惯问题,总觉得写法上有些怪异,使用起来有心里负担,而且其它语言中似乎也没见过有这样的用法。

之前我们讨论的都是纯粹的单例,应用程序生命周期中只存在一个实例。而现在我们需要做一下扩展,将程序改造为允许在其声明周期内存在指定个数的实例,是一种类似于数据库连接池这样的概念。明确概念之后,代码实现也比较简单。

public class Singleton { private static int size = 5; private static ArrayList<E> instanceList = new ArrayList; static { for(int i = 0; i < size; i++) { instanceList.add(new Singleton; } } private Singleton(){} public static Singleton getInstance(){ Random random = new Random(); return (Singleton) instanceList.get(random.nextInt; }}

关于单例模式,暂告一段落,后面再继续聊聊其它的模式。

TO BE CONTINUED

<a rel="license" href="

</a><br />本作品采用<a rel="license" href=" 4.0 国际许可协议</a>进行许可。

本文由时时彩平台发布于时时彩平台-编程,转载请注明出处:时时彩平台一旦发生了重排序操作

关键词: