Java:如果同步发生更改,同步不会阻塞

时间:2019-05-23 22:01:21

标签: java multithreading

相关的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 个答案:

答案 0 :(得分:3)

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

    在字段初始值设定项中创建的
  • ObjA

  • sleep(1000)

    之前的行中创建了
  • ObjB

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

由于启动线程后您拥有sleep(100),因此在主线程到达其a.lockObj时,该线程将已更改synchronized (a.lockObj)以引用 ObjB 阻止,这样将锁定在另一个对象上

作为另一个对象,代码不会阻塞。

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