对java内存模型中“有序性”的理解

书上说,对于java内存模型的有序性可以总结为一句话:“在线程内部观察,那么所有的操作都是有序的,在一个线程中观察另外一个线程,所有的操作都是无序的”。

老实说,我一开始看到这句话一面懵逼,什么玩意,经过了一个晚上的思考,我似乎理解了其中的意思。


1、为什么说:在线程内部观察,那么所有的操作都是有序的?

首先,为什么说在在线程内部观察,那么所有的操作都是有序的?因为我们知道程序的实际执行的顺序不一定和我们程序实际写的顺序是一致的,因为虚拟机编译执行时,也就是把class文件编译成本地代码执行时,可能会对代码进行优化,导致代码被重新排序,我们把这个叫做“指令重排序优化”。但是无论怎么重排序,单线程内部,最终的执行结果是和没有重排序的结果是一样的,因为即使把指令重新排序,肯定也不可能影响执行结果。因此,我们可以把单线程的内部看做是as-if-serial语义的,也就是类似串行的。

那请问为什么同步块,即synchronized即使有指令重排序,还是可以实现有序性呢??

根据之前说的,在一个线程内部,本来就是存在指令重排序的,但是我们根据as-if-serial语义来说,可以办他看成是类似串行的语义,相当于是有序的。而当线程运行到同步块时,会加锁,此时,其他线程无法获得锁,直到当线程释放锁时,其他线程才可以获得锁,执行该方法,也就是说此时同步块内的方法是单线程的,因此,synchronized可以实现有序性。


2、为什么说:在一个线程中观察另外一个线程,所有的操作都是无序的

这也是因为我提到的”指令重排序优化“ ,但是注意,指令重排序只有在遇到多线程问题的时候才会可能导致线程安全的问题,而在单线程内部的“指令重排序优化”是不会导致有序性问题的。

根据上面的代码,如果initialized没有被声明为volatile,那么会出现线程安全问题,因为因为执行线程B的时候,initialized=true这个代码,可能会被优化到完成配置之前执行,这就导致了线程A还没配置,线程B就开始一位线程A配置好了,就执行后面的内容了。因此必须使用volatile,来禁止指令重排序。

因此,什么叫做:在一个线程中观察另外一个线程,所有的操作都是无序的。这就表示你不知道另外一个线程里面到底是怎么执行的,而他执行的顺序对本线程会产生影响。

因此,我们可以利用同步块---synchronized和volatile来实现线程之间的有序性。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值