返回信息流看到 java 的 happen-before 的规则,里面有一条是传递性,也就是 如果操作A happen—before操作B,操作B happen—before操作C,那么可以得出A happen—before操作C。这里有点疑惑,如果没有这种传递性的规定,感觉对实际系统同样没有影响啊?如果去掉这一条规则会出现什么样的问题?
这是一条镜像帖。来源:北邮人论坛 / java / #56311同步于 2017/5/20
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
java happen—before 的问题
hyx2011
2017/5/20镜像同步4 回复
订阅后,新回复会通过你的通知中心匿名送达。
4 条回复
但是失去传递性对整体没啥影响吧
【 在 ml3615556 (Andy) 的大作中提到: 】
: 这是对Java多线程编程模型的描述,去掉传递性类似与数学中比较符号失去传递性一样
这是对语义的规定。比如:
有两个成员变量x,y,其中y是volatile的。初始值都是0.
int x = 0;
volatile y = 0;
线程1先写x,后写y。
Thread thread1 = new Thread(() -> {
x = 1;
y = 2;
});
线程2先读y,后读x。如果读到y==2,就打印读到的x的值,如果y不是2就不打印:
Thread thread2 = new Thread(() -> {
int yy = y;
int xx = x;
if (yy == 2) {
System.out.println(xx);
}
});
请问线程2如果读到y==2,是否一定也能读到x==1?
答案是:一定。只要读到y==2,一定读到x==1。
但是要解释为什么,就要利用happen-before的传递性了。下面用简写:
x po y: x comes before y in the program order
x sw y: x is synchronized with y
x hb y: x happens before y
同一个线程里的动作符合程序顺序。所以,thread1里,“x=1” po “y=2“。同样,thread2里,“yy=y” po “xx=x”。
两个线程之间,thread2里对volatile变量y的读,读到了thread1里对y的写写入的值(即读到了2),那么就有“y=2” sw “yy=y“,其中前者来自thread1,后者来自thread2。
Java Memory Model里,happens-before关系是program order和synchronized with的并集。即所有的po和sw都是hb。于是有:
“x=1” hb “y=2”
“y=2” hb “yy=y”
“yy=y” hb “xx=x”
又因为hb具有传递性,所以“x=1” hb “xx=x”。又因为除此之外没有对x的写操作,所以thread2里那个“xx=x”一定能读到1。
如果hb不具有传递性,那么thread1里的“x=1”和thread2里的“xx=x”之间就没有hb关系,也就不能保证thread2一定能读到x=1了。这样的话volatile产生的sw关系就起不到同步作用了。
【 在 hyx2011 的大作中提到: 】
: 看到 java 的 happen-before 的规则,里面有一条是传递性,也就是 如果操作A happen—before操作B,操作B happen—before操作C,那么可以得出A happen—before操作C。这里有点疑惑,如果没有这种传递性的规定,感觉对实际系统同样没有影响啊?如果去掉这一条规则会出现什么样的问题?