多线程/并发-happens-before-有一处不理解-大龄程序员求助

京都盖饭小白领 2018-08-15 11:35:41
关于多线程 happens-before的,有这么几个规则(JDK1.5):

程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。

《java并发编程的艺术》中提到这么一个例子:


假设线程A执行writer()方法之后,线程B执行reader()方法。根据happens-before规则,这个
过程建立的happens-before关系可以分为3类:
1)根据程序次序规则,1 happens-before 2;3 happens-before 4。
2)根据volatile规则,2 happens-before 3。
3)根据happens-before的传递性规则,1 happens-before 4。
上述happens-before关系的图形化表现形式如下。


这里的1)根据程序次序规则,1 happens-before 2;3 happens-before 4。
这个是我不理解的,如果这个成立,那么该书上另外一个例子就有问题了。

另一个例子为:


书上说可能:


这里矛盾了啊,上图中根据happens-before,读对象的普通域i不能重排序到读对象的final域j上面去啊。


到底哪个例子正确,求解!
...全文
267 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
cg_Amaz1ng 2019-10-17
  • 打赏
  • 举报
回复
final跟volatile没有关系吧
verejava 2018-08-19
  • 打赏
  • 举报
回复
并发编程 之 线程 售票排队例子

http://www.verejava.com/?id=17236617240060
ninuxGithub 2018-08-16
  • 打赏
  • 举报
回复
下面是happens-before原则规则:

程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;
锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作;
volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作;
传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;
线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作;
线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;
线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;
对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始;


网上找的
ninuxGithub 2018-08-16
  • 打赏
  • 举报
回复
加入有个代码:
int a=1;
int b=1;
int c= a + b;
正常的情况下, java虚拟机会按照顺序执行, 但是在特定的情况下虚拟机在编译的时候会去优化代码

例如先初始化b 在初始化 a 最终的结果不受到影响

volatile的作用主要是在多线程的情况下, 告诉每个线程该变量是一个系统共享的变量,寄存的位置有点特殊,在主的内存里面 。 保证原型性,每次要修改的时候都去读一下主内存的那个值 , 你可以去看看automIntger 原则性的实现原理 cas ,caw;
内置屏障: 是告诉java虚拟机不要去优化我们写的code 让其按照我们的code执行下去 得到最终的结果


个人的见解

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧