杭州集团公司网站建设,网站推广软件排名,wordpress 4.7.2 提权,国际网站怎么开通单例的目的是为了保证运行时Singleton类只有唯一的一个实例#xff0c;用于一些较大开销的操作。 饿汉式#xff08;没有线程安全问题#xff09;: ‘ 由于使用static关键字进行了修饰#xff0c;只能获取到一个对象#xff0c;从而达到了单例#xff0c;并且在Singleton…单例的目的是为了保证运行时Singleton类只有唯一的一个实例用于一些较大开销的操作。 饿汉式没有线程安全问题: ‘ 由于使用static关键字进行了修饰只能获取到一个对象从而达到了单例并且在Singleton类初始化的时候就创建了对象加载到了内存。 问题在没有使用这个对象的情况下就加载到内存是一种很大的浪费。 针对这种情况有一种新的思想提出——延迟加载也就是所谓的懒汉式。 懒汉式存在线程安全问题: 这种方法在调用Singleton.getInstance()时才会创建对象起到了延迟加载的作用。 问题这样的写法在多个线程同时运行时很有可能会产生多个实例对象导致线程安全问题。 使用同步的方法解决这个问题加上synchronized关键字代码如下 使用同步的代价是会在一定程度上降低程序的并发度并且锁定整个方法很消耗资源原本采用延迟加载是为了节省资源 所以降低锁的细粒度代码如下 但是这样的写法线程还是不安全因为两个线程可以同时进入if语句线程A实例化对象返回之后线程B不用经过判断 能再实例化对象并且返回另一个对象。为了解决这个问题引入了臭名昭著的双重锁机制 上面的代码看似解决了线程安全问题也起到了延迟加载的作用但是双重锁机制是没有办法工作的有一篇文章解释的非常 深刻http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html 在参考了一些资料我认为双重锁机制之所以不能正常运行是因为在new对象的时候是有三个步骤的分配内存空间 初始化对象然后将内存地址赋值给变量在这么三个步骤中极有可能会在操作上进行重排序在重排序的情况下还没有初始化 对象先将内存地址赋值给了变量这种情况是可能存在的当线程B进入时发现变量不为null就会直接返回这个实例然而此时 可能拿到的是还没有初始化完成的对象。所以双重锁机制是不提倡使用的。 在http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl文章中有提出在新的内存模型下实例字段使用volatile可以解 决双重锁检查的问题因为在新的内存模型下volatile禁止了一些重排序但是同时使用volatile的性能开销也有所上升。 所以又提出一种新的模式——Initialization on Demand Holder. 这种方法使用内部类来做到延迟加载对象在初始化这个内部类的时候 JLS(Java Language Sepcification)会保证这个类的线程安全。代码如下 转载于:https://www.cnblogs.com/ckgame/p/8328347.html