2

考虑以下代码片段:

 Object bar1  = new ... ; 
 Object bar2 = new ... ; 


 Object foo = (either bar1 or bar2) ; 

现在, foo 在程序的不同时间可以是 bar1 或 bar2。我只是想检查 synchronized(foo) 是否会锁定相应的 bar1 或 bar2。鉴于没有在 Java 中复制对象,这似乎是最有可能的情况。这个对吗?

4

3 回答 3

6
Object bar1 = new Object();
Object foo = bar1;
synchronized(foo) {
    ...
}

将锁定foo== bar1

然而,这是一个奇怪且容易出错的结构。例如:

  • 线程 1 到达您的方法和 foo == bar1
  • 线程 1 到达同步块并锁定 bar1
  • 线程 2 到达您的方法和 foo == bar2
  • 线程 2 到达同步块并锁定 bar2

现在您有 2 个线程同时运行同步块。我真的找不到你想要那个的理由。如果你这样做了,那么块可能不应该被同步,你应该使用不同的锁定策略。

另请参阅此相关帖子

于 2012-08-21T10:44:22.863 回答
2

是的,它将锁定foo指向的任何对象。但是,我强烈建议你做foofinal 以避免这样的事情:

Object foo = bar1;
synchronized(foo) {
   foo = bar2;
}

因为它会导致几个线程看到不同的锁。另请参阅这个问题:锁定可变对象 - 为什么它被认为是一种不好的做法?

于 2012-08-21T10:47:05.590 回答
2

是的。您不是在参考上同步,而是在底层对象上同步。

每个对象都有一个关联的监视器,当您使用synchronized. 从这里

在 Java 虚拟机中,每个对象和类在逻辑上都与一个监视器相关联。对于对象,关联的监视器保护对象的实例变量。对于类,监视器保护类的类变量

于 2012-08-21T10:45:44.813 回答