没有同步顺序的程序

尤金

我正在查看我发现并开始推理SO(同步顺序)或更准确地说,缺少它的最简单示例之一。考虑下面的例子:

int a, b; // two shared variables 

Thread-X:

 void threadX() {
     synchronized(this) {
         a = 1;
     }
     synchronized(this) {
         b = 1;
     }
 }

还有一个读者线程Thread-Y

 void threadY() {
     int r1 = b;
     int r2 = a;
 }

为简单起见,让我们假设Thread-Y完全按此顺序读取:它肯定会先读取b,然后a(与写入相反)。

允许阅读线程查看[1, 0](就像之前b=1发生的那样)。我想我也明白为什么:因为两个动作之间没有同步顺序,因此没有发生之前,根据这是一个数据竞争 a=1JLS

当一个程序包含两个冲突的访问,而这些访问不是由先发生关系排序的,它被称为包含数据竞争。

因此阅读aandb是两个活泼的阅读,所以看到b=1anda=0是允许和可能的。

现在这反过来又允许 JVM 在 writer 中进行锁粗化,所以它变成:

 void threadX() {
     synchronized(this) {
         a = 1;
         b = 1;
     }
 }

我的问题是,如果读者最初是这样写的:

void threadY() {
     synchronized(this) {
         int r1 = b;
     }

     synchronized(this) {
         int r2 = a;
     }
 }

仍然允许锁粗化吗?我知道答案,但我也想听听有根据的解释。

普文杰尔

锁粗化(和重新排序)是允许的,因为同步读取器要么在粗化锁之前或之后被排序。当粗化锁被持有时,他们将永远无法看到发生了什么,因此无法观察到锁定代码内部的任何重新排序。

更多信息请参见:https : //shipilev.net/blog/2016/close-encounters-of-jmm-kind/#myth-barriers-are-sane

顺便说一句,好问题。前段时间我也在为这个特定的例子而苦苦挣扎:)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章