代码之家  ›  专栏  ›  技术社区  ›  ealeon

Java:如果同步发生变化,它不会阻塞

  •  0
  • ealeon  · 技术社区  · 6 年前

    相关的 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 从第一个街区变了。为什么?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Andreas dfa    6 年前

    你在创造 对象,因此让我们命名它们以供参考:

    • 奥比亚 在字段初始值设定项中创建

    • 目标 在前面的行中创建 sleep(1000)

    这个 synchronized (a.lockObj) 线程中的块正在锁定 奥比亚 .

    既然你已经 sleep(100) 启动线程后,线程将发生更改 a.lockObj 参考 目标 当主线程到达它的 同步(a.lockObj) 布洛克,所以 锁定其他对象 .

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

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