如果你锁定了一个对象,你是否锁定了它的所有方法?

If you have a lock on an object, do you have a lock on all its methods?

假设我们有一个对象 foo:

class Foo(){
  public synchronized void instanceMethod(){}
}

var foo = new Foo();

如果我锁定了 foo:

synchronized(foo){
  foo.instanceMethod();
}

我是否也锁定了 instanceMethod() 调用?另一种提问方式——如果我锁定了 foo,另一个线程可以调用 foo.instanceMethod()(同时)吗?

if I have a lock on foo, can another thread call foo.instanceMethod()?

他们可以调用它,但调用将等到执行离开您的块 synchronizedfoo,因为 instanceMethodsynchronized。声明一个实例方法 synchronized 与将其整个主体放在 this.

上的块 synchronized 中大致相同

如果instanceMethod 没有同步,那么调用当然不会等待。

不过请注意,您显示的 synchronized 块是不必要的:

synchronized(foo){       // <==== Unnecessary
  foo.instanceMethod();
}

因为instanceMethodsynchronized,所以可以是:

foo.instanceMethod();

...除非块中还有其他东西。

class Foo {
    public synchronized void a() { //Do something }
    public void b() {
        synchronized(this) { // Do something }
    }
    public void c() { // Do something }
}

然后:

Foo foo = new Foo();
foo.a();
foo.b();
synchronized(foo) { foo.c(); }

这 3 种方法在同步方面都非常相似。

没有“锁定”方法这样的东西。锁定仅在对象上完成。标记方法 synchronized 只是使其锁定实例(或其静态方法的 class 对象)。

当您访问锁定对象上的方法时,执行将被阻止,因为线程无法检索指定对象的 monitor - 甚至在方法执行之前被称为。因此 foo.a() 在获取 foo.

时将被阻止

添加...

突然想起一件事。如果你有线程 A 调用 foo.a() 并且它需要很长时间才能完成,而此时另一个线程调用 foo.c(),那么 foo.c() 仍然会被阻塞直到 foo.a() 完成。