0
static ConcurrentHashMap k;

X x; 
//line 3: 
synchronized(k){ x = k.get("LL");}

// line 5 

// line 12: 
synchronized(k){if(x.b){x.b = false;}} 

'k' 是共享地图。第一个线程通过第 3 行,当线程 1 在第 5 行时,第二个线程通过第 3 行,线程一将 xb 更改为 false,线程 2 看到什么 xb?第 5 行旨在显示线程 2 在线程 1 进入第二个同步块之前获得它的 x

4

2 回答 2

2

您对术语“第一个线程”和“第二个线程”的定义有些过分;您的问题预设了进入第一个synchronized块的第一个线程也将是进入第二个synchronized块的第一个线程,但实际上没有理由期待这一点。

然而,第一个synchronized块并没有做任何非常相关或有趣的事情——你的代码片段中没有任何东西 mutates k,第一个synchronized块只是访问它——所以我将忽略它是synchronized. 这将稍微简化定义:现在“第一个线程”表示进入第二个synchronized块的第一个线程,“第二个线程”表示进入第二个synchronized块的第二个线程。(到目前为止还好吗?) 定义的问题。. .

假设不可能有其他线程进入并设置x.btrue- 或者,就此而言,第一个线程这样做,在您引用的代码段之后的代码中 - 同样,两个线程不可能完全不同结果是k.get("LL")由于其他地方发生的事情 - 然后第二个线程将x.b显示为false,就像人们天真地期望的那样。这是因为

如果一个动作发生在另一个动作之前,那么第一个动作对第二个动作可见并在第二个动作之前排序。

监视器上的解锁发生在该监视器上的每个后续锁定之前。

(以上两个引文均来自Java 语言规范,Java SE 7 版的第 17.5.5节;有关更多形式,请参见该部分及其之前的部分。)

于 2012-11-04T03:25:06.420 回答
1

解释不是很清楚,但这就是我的理解。

由于线程 1 位于第 5 行(已经通过第 3 行)并且尚未到达第 12 行(并且您所说的介于 3 和 12 之间的某处线程 1 将 xb 设置为 false),线程 2 应该将 xb 视为刚刚设置的任何线程它到(这是错误的)。虽然我没有看到线程 2 实际上关心在第 3 行中看到 xb。而且我不清楚为什么第 5 行(我没有看到)不同步,但是将其设置为 false 的第 12 行是同步的。

于 2012-11-04T03:29:32.957 回答