synchronized总结:怎么保证可见性、有序性、原子性?

synchronized的原子性

synchronized 底层实际上通过JVM来实现的,同一时间只能有一个线程去执行synchronized 中的代码块。

原子性:既然同一时间只有一个线程去运行里面的代码,那么这个操作就是不能被其它线程打断的,所以这里天然就具有原子性了。

synchronized通过内存屏障保证可见性

老王:小陈啊,之前我们讲volatile的时候说过,volatile的可见性是通过什么来保证的

小陈:这个我还记得啊,volatile是通过内存屏障来保证可见性的Load屏障保证volatile变量每次读取数据的时候都强制从主内存读取Store屏障每次volatile修改之后强制将数据刷新会主内存

小陈:老王啊,难道说synchronized关键字也是通过内存屏障来保证可见性的?

老王:哈哈,小陈你的猜想没错。

我们都知道sychronized底层是通过monitorenter的指令来进行加锁的、通过monitorexit指令来释放锁的

但是很多人都不知道的一点是,monitorenter指令其实还具有Load屏障的作用

也就是通过monitorenter指令之后,synchronized内部的共享变量每次读取数据的时候被强制从主内存读取最新的数据。

同样的道理monitorexit指令也具有Store屏障的作用,也就是让synchronized代码块内的共享变量,如果数据有变更的,强制刷新回主内存。

这样通过这种方式,数据修改之后立即刷新回主内存,其他线程进入synchronized代码块后,使用共享变量的时候强制读取主内存的数据,上一个线程对共享变量的变更操作,它就能立即看到了。

老王:画个图给你看一下,大概是这样子的:

小陈:原来是这样啊,synchronized底层竟然也是通过内存屏障来保证可见性的。

synchronized使用内存屏障来保证有序性

老王:那我再问你,synchronizd是怎么保证有序性的,想必聪明如你,已经知道答案了吧

小陈:哈哈,之前volatile通过内存屏障来保证有序性的,我想synchronized也是吧。

老王:我们知道四条禁止指令重排序的内存屏障,这4条禁止重排序的内存屏障分别为:

StoreStore屏障:禁止StoreStore屏障的前后Store写操作重排

LoadLoad屏障:禁止LoadLoad屏障的前后Load读操作进行重排

LoadStore屏障:禁止LoadStore屏障的前面Load读操作跟LoadStore屏障后面的Store写操作重排

StoreLoad屏障:禁止LoadStore屏障前面的Store写操作跟后面的Load/Store 读写操作重排

同样的道理啊,也是通过monitorenter、monitorexit指令嵌入上面的内存屏障;monitorenter、monitorexit这两条指令其实就相当于复合指令,既具有加锁、释放锁的功能,同时也具有内存屏障的功能。

再画个图给你看一下,是怎么禁止重排序的:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值