双重检测加锁为什么要使用volitail_解读并发多线程中dcl(double check lock)的时候被操作共享变量需要使用volatile进行修饰...

下边拿dcl单例模式进行举例说明:

public class Singleton {

private int num=100;

private static Singleton singleton;

private Singleton (){}

public static Singleton getSingleton() {

if (singleton == null) {

synchronized (Singleton.class) {

if (singleton == null) {

singleton = new Singleton();

}

}

}

return singleton;

}

}

曾经误以为是jmm的模型中,后续线程T2中工作内存副本中先得到了null(通过了第一次null判断,之后别的线程T1获取锁创建了实例但是未能及时通知T2改变)未被及时通知变化导致的了,所以导致进入在第二次为空判断时还是null,后来知道这么理解是错误的,看下边红字就知道了

补充一些知识:

java内存模型与synchronized关键字

synchronized关键字强制实施一个互斥锁,使得被保护的代码块在同一时间只能有一个线程进入并执行。当然synchronized还有另外一个 方面的作用:在线程进入synchronized块之前,会把工作存内存中的所有内容映射到主内存上,然后把工作内存清空再从主存储器上拷贝最新的值(经测试sleep,wait,park这些主动释放cup的操作都有类似作用)。而 在线程退出synchronized块时,同样会把工作内存中的值映射到主内存,但此时并不会清空工作内存。这样一来就可以强制其按照上面的顺序运行,以 保证线程在执行完代码块后,工作内存中的值和主内存中的值是一致的,保证了数据的一致性!

所以由synchronized修饰的set与get方法都是相当于直接对主内存进行操作,不会出现数据一致性方面的问题。

真正原因:

singleton = new Singleton();

这一步实际的操作可被分为了三步:

1分配内存空间属性赋零值num=0(零值不应定就是0还有可能是false等);

2属性赋初值或构造函数值num=100

3将singleton位置指向此处内存空间

但是这三步有可能被cpu进行指重排序,导致T1在创建singleton时先1后3(则此时singleton已有null变为有真正的指向),若这时T2得到cup进来了发现singleton已不为null,便将其拿入工作副本实用,则会出现问题;

这种概率极小但一旦发生在某些业务中可能就是致命的,所以此处需要禁止指令重排序,而volatile便有这个功能(可见性,禁止指令重排序)

代码改为:

public class Singleton {

private int num=100;

private volatile static Singleton singleton;

private Singleton (){}

public static Singleton getSingleton() {

if (singleton == null) {

synchronized (Singleton.class) {

if (singleton == null) {

singleton = new Singleton();

}

}

}

return singleton;

}

}

补充一个关于volitail小知识:

伪共享问题:volitail 会触发缓存一致性[intel用的是MESI协议],缓存一致性每次都是按照行为单位触发的(缓存行的概念),行内可能有多个变量比如A,B  一旦A失效整个行的变量都将失效,(所以如果线程1只用了volitail A,线程2只用了volitail B 但是两个线程的缓存行却都是A和B,那就会触发不必要的缓存一致性同步)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值