【问题标题】:Java: synchronization does not block if it changesJava:如果发生变化,同步不会阻塞
【发布时间】:2019-05-23 22:01:20
【问题描述】:

相关Java will synchronized block if changed?

 public class TestConcurrentTwo {
     public static void main(String[] args) {

         class lock {
             public Object lockObj = new Object();
             int protectedValue = 0;
         }
         lock a = new lock();

         Thread t = new Thread(() -> {
             try {
                 synchronized (a.lockObj) {
                     System.out.println("from first block start");
                     System.out.println(a.protectedValue);
                     a.lockObj = new Object();
                     Thread.sleep(1000);
                     System.out.println(a.protectedValue);
                     System.out.println("from first block done");
                 }
             } catch (InterruptedException x) {}
         });
         t.start();
         try {
             Thread.sleep(100);
         } catch (InterruptedException x) {}

         synchronized (a.lockObj) {
             System.out.println("from second block start");
             a.protectedValue++;
             System.out.println("from second block done");
         }

         System.out.println(a.protectedValue);
     }
 }

输出:

from first block start
0
from second block start
from second block done
1
1
from first block done

在相关答案中,它们都持有原始引用,因此第二个块应该被阻止,直到第一个块完成。

但是,一旦a.lockObj 从第一个块更改,第二个块确实进行了。为什么?

【问题讨论】:

  • 你的两个线程使用不同的锁。第一个线程持有a,lockObj 引用的第一个Object 实例,第二个线程持有a.lockObj 引用的第二个Object 实例。这很容易避免:不要重新分配正在同步的对象
  • 其他答案中的一些措辞使 IMO 感到困惑,特别是“参考”一词的使用,让我们将成员 a.lockObj 称为 参考a.lockObj 引用的Object引用的对象。同步取决于被引用的对象,而不是引用。有两个不同的引用对象用于同步;结果痛苦。

标签: java multithreading


【解决方案1】:

您正在创建 两个 对象,所以让我们为它们命名以供参考:

  • ObjA 在字段初始化器中创建

  • ObjBsleep(1000) 之前的行中创建

线程中的synchronized (a.lockObj) 块正在锁定ObjA

由于你在启动线程后有sleep(100),所以当主线程到达它的synchronized (a.lockObj) 块时,线程将更改a.lockObj 以引用ObjB,因此将 锁定不同的对象。

作为不同的对象,代码不会阻塞。

提示:锁在对象上,而不是引用变量上。

【讨论】:

    猜你喜欢
    • 2019-10-10
    • 2021-10-13
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2018-04-06
    • 2019-10-08
    • 1970-01-01
    • 2018-05-11
    相关资源
    最近更新 更多