如果您拥有对象的锁,那么您是否拥有其所有方法的锁?

时间:2019-02-11 07:48:10

标签: java synchronized

假设我们有一个对象foo:

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

var foo = new Foo();

如果我锁定foo:

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

我也锁定了instanceMethod()通话吗?提出问题的另一种方式-如果我对foo有锁,另一个线程可以同时调用foo.instanceMethod()吗?

2 个答案:

答案 0 :(得分:3)

  

如果我对foo有锁,另一个线程可以调用foo.instanceMethod()吗?

他们可以调用它,但是调用将一直等到执行离开synchronized上的块foo为止,因为instanceMethodsynchronized。声明实例方法synchronized与将其整个主体放在synchronized上的块this中相同。

如果instanceMethod 同步,则通话当然不会等待。

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

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

由于instanceMethodsynchronized,因此可能是:

foo.instanceMethod();

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

答案 1 :(得分:2)

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(); }

这三种方法在同步方面都差不多。

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

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

添加...

我突然想起了什么。如果您的线程A调用了foo.a(),并且要花很长时间才能完成,而此时另一个线程调用了foo.c(),那么foo.c()仍将被阻塞,直到{{1} }完成。