【问题标题】:will before synchronized statement before another synchronized nock? [duplicate]将在同步语句之前在另一个同步诺克之前? [复制]
【发布时间】:2018-10-30 16:10:09
【问题描述】:

如果有两个全局无 volatile int 变量 a , b 和 object obj ;线程 1 有:

 1 ++a;
 2 synchronized(obj){
 3   ++b; 
 4 }
 5 print a

头 2 有:

 1 synchronized(obj){
 2   ++b; 
 3 }
 4 print a

所以我的问题是:

1、线程1中1行代码可以在4行代码之后重新排序吗?

2、如果线程1先lock unlock obj,那么线程2做;当 print a 时,线程 2 也会正确获取 a

【问题讨论】:

  • 如果这些字段都不是volatile,则所有赌注都关闭。

标签: java multithreading


【解决方案1】:

Java 语言规范中定义的以下规则适用于您的代码:

17.4.4. Synchronization Order

同步动作在动作上产生synchronized-with关系,定义如下:

  1. 监视器m 上的解锁 操作同步 m 上的所有后续锁定 操作(其中定义了“后续”根据同步顺序)。

17.4.5. Happens-before Order

两个动作可以通过 happens-before 关系进行排序。如果一个动作在另一个动作之前发生,那么第一个动作对第二个动作可见并排在第二个动作之前。

如果我们有两个动作xy,我们写hb(x, y) 表示x happens-before y

  1. 如果xy 是同一线程的操作,并且x 在程序顺序中位于y 之前,则hb(x, y)

  2. 如果一个动作x同步一个后续动作y,那么我们也有hb(x, y)

  3. 如果hb(x, y)hb(y, z),那么hb(x, z)

现在让我们将它应用到您的代码中:

A1 ++a;
A2 synchronized(obj){
A3   ++b; 
A4 }
A5 print a
B1 synchronized(obj){
B2   ++b; 
B3 }
B4 print a

规则 2 规定:

A1 -> A2 -> A3 -> A4 -> A5
B1 -> B2 -> B3 -> B4

结果取决于哪个线程首先到达synchronized 块。如果线程 B 先到达,就会出现问题,其中规则 1 + 3 状态:

B3 -> A2

综合:

A1 →→→→→→→→→→→→→ A2 → A3 → A4 → A5
              ↑
B1 → B2 → B3 →→→ B4

A1 (++a) 和 B4 (print a) 之间没有 happens-before 关系,因此结果无法预测。


如果线程 A 先到达,规则 1 + 3 状态:

B4 -> B1

合并

A1 → A2 → A3 → A4 →→→ A5
                   ↓
                   →→ B1 → B2 → B3 → B4

规则 4 然后声明 hb(A1, A5)hb(A1, B4),这意味着 ++a 保证发生在两个 print a 语句之前。


回答您的具体问题:

线程 1 中的 4 行代码之后可以重新排序 1 行代码吗?

在线程 1 中?没有。
从线程 2 中可以看出?是的,见上文。

如果线程 1 先 lock unlock obj ,那么线程 2 做;打印 a 时线程 2 也会正确获取 a 。

是的,如果线程 1 先锁定,线程 2 将打印 a 的更新值,见上文。

【讨论】:

    【解决方案2】:

    同步块之前、期间或之后的语句不能跨越这些边界重新排序。它们可以重新排序,语句也在这些边界的同一侧。

    如果这些字段都不是易变的,则所有赌注都关闭。

    没有同步也是如此,但是同步也会引入完整的内存屏障。

    线程 1 中的 4 行代码之后可以重新排序 1 行代码吗?

    不能在第 2 行之后排序。

    如果线程 1 先 lock unlock obj ,那么线程 2 做;那么线程 2 在打印 a 时是否会正确获取 a 值。

    如果线程 1 在线程 2 之前进入 synchronized,是的。但是,线程 2 可能会先执行,在这种情况下它可能会看到旧值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多