双重检查锁单例真的线程安全吗?
当A线程执行到第二步(3:设置instance指向刚分配的内存地址,此时对象还没被初始化)变量single指向内存地址之后就不为null了,此时B线程进入第一个if,由于single已经不为null了,那么就不会执行到同步代码块,而是直接返回未初始化对象的变量single,从而导致后续代码报错。 解决方案问题也搞清楚了,接下来我们就来看下如何解决这个问题。解决问题的关键就在于volatile关键字,原因就在于它的可见性: 写volatile修饰的变量时,JMM会把本地内存中值刷新到主内存 读 volatile修饰的变量时,JMM会设置本地内存无效 在多线程环境下,一个线程对共享变量的操作对其他线程是不可见的,Java提供了volatile来保证可见性,当一个变量被volatile修饰后,表示着线程本地内存无效,当一个线程修改共享变量后他会立即被更新到主内存中,其他线程读取共享变量时,会直接从主内存中读取。 当然,synchronize和Lock都可以保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。 更正后的单例
对比上面单例,下面单例在私有静态变量single前面加了修饰符volatile能够防止JVM指令重排,从而解决了single对象可能出现成员变量未初始化的问题。 (编辑:鹤壁站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |