【问题标题】:locking behavior of synchronous method同步方法的锁定行为
【发布时间】:2019-01-25 17:44:05
【问题描述】:

一位开发人员与我争论说,如果我们从另一个对象A 中的同步方法调用对象B 中的同步方法,则获取对象B 上的对象锁定没有额外成本,因为我们已经锁定了对象A。我该如何反驳?

开发者理论- “当您调用同步方法时,线程会获取该方法中使用的所有对象的锁定。”

class ObjectA {

public synchronized void methodA() {
  methodB();
  // do something else
}

}

class ObjectB {

public synchronized void methodB() {
  // do something
}

}

【问题讨论】:

  • lock on all objects used in that method 这显然是错误的。如果methodA 中的代码正在执行但不在methodB 中,则任何线程都可以成功调用并获取methodB 的锁。应该能够编写代码来证明这一点。
  • 有时获取监视器 (synchronized) 锁所需的时间较短,例如一段时间后再次获取相同的锁。我不认为它会减少到“没有时间”,但这是不可行的。它可能会减少到实际上可能发生的“实际上没有时间”。
  • 我可以轻松地让其他线程锁定 objectB,但我的开发伙伴会继续毫无根据地争论。我想要明确的证据,我正在寻找在执行代码时打印指令集的方法。你有关于如何做到这一点的任何参考资料吗?
  • continue to argue baselessly 这是人事问题,没有什么可以通过讨论解决的。在反模式列表中查找“Corn Cob”。
  • 有很多例子展示了死锁。这应该是证据。

标签: java synchronization


【解决方案1】:

告诉你的开发伙伴:

执行静态同步方法的线程持有类的锁,执行非静态同步方法的线程持有该方法所在对象的锁已被调用。 (这两个锁是不同的,这些线程不会互相阻塞)。

举个例子:

public class Counter {
    private int count = 0;
    public void increment() {
       synchronized (this) {
       count++;
    }
}
public int getCount() {
    synchronized (this) {
        return count;
    }
}
}

每个创建的 Java 对象,包括每个加载的类,都有一个关联的锁或监视器。

将代码放在同步块中会使编译器在执行代码之前附加指令以获取指定对象上的锁,然后释放它(因为代码正常完成或异常完成)。

在获取锁和释放锁之间,线程被称为“拥有”锁。在线程 A 想要获取锁的时候,如果线程 B 已经拥有它,那么 线程 A 必须等待线程 B 释放它。

在您的情况下,将在 ObjectB 类的对象上调用 methodB(),因为它是一个非静态方法。

因此,当进入 methodB() 时,线程将立即拥有对 ObjectB 类的对象(正在调用该方法的对象)的锁定它看到 methodB() 已同步

【讨论】:

  • 哦,天哪,我说了同样的话,响应是“当您调用同步方法时,线程获取该方法中使用的所有对象的锁定。”是的,我什至无法理解这里的白痴
  • 因此,结论(也可能是问题的答案)是,当我们调用同步方法时,线程只获取用于调用该方法的对象的锁,并且 不是 该方法中使用的所有对象。正确的?我会在答案中添加这一点,以确保 OP 提出的问题得到正确回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多