多级java行为的同步

多级java行为的同步,java,synchronization,Java,Synchronization,如下面的示例所示,一旦在call方法中锁定了一个对象,就不需要进一步的方法来同步关键字 public class Prac { public static void main(String[] args) { new Prac().call(); } private synchronized void call() { further(); } private synchronized void furthe

如下面的示例所示,一旦在
call
方法中锁定了一个对象,就不需要进一步的方法来同步
关键字

public class Prac
 { 
    public static void main(String[] args)
    {
      new Prac().call();
    }

    private synchronized void call()
    {
      further();
    }

    private synchronized void further()
    {
      oneMore();
    }

    private synchronized void oneMore()
    {
      // do something
    }
 }
但是,如果我仍然将
synchronized
关键字添加到
further
onceMore
,java在这种情况下会做什么?java是否检查是否需要锁?或者,由于方法调用在同一堆栈中,它只是继续进行,而不检查是否需要锁,因为已经获得了锁


注意:我的疑问是java在这种情况下会如何表现,我不确定,但我认为它不同于偏向锁定。

事实上,java每次进入同步方法时都会检查当前线程是否有锁

private synchronized void oneMore()
    {
      // do something
    }
这相当于

private void oneMore(){
      synchronized(this){
      // do something
    }
}
但是因为java中的内在锁是可重入的;如果一个线程拥有锁,它不会在进入另一个同步块后重新获取它,如您的示例所示。否则,这将创建死锁

更新:在下面回答您的评论。从Java Concurrency的实践来看:

Reentrancy is implemented by associating with each lock an acquisition count 
and an owning thread. When the count is zero, the lock is considered unheld. 
When a thread acquires a previously unheld lock, the JVM records the owner 
and sets the acquisition count to one. If that same thread acquires the lock 
again, the count is incremented, and when the owning thread exits the
synchronized block, the count is decremented. When the count reaches zero, 
the lock is released.
因此,检查是否获取了锁相当于一条if语句(或多或少),即持有所属线程的变量是否等于试图获取锁的线程


但是,正如您所指出的,私有方法上不需要synchronized关键字。通常,您应该尝试删除不必要的同步,因为这通常会导致性能下降。

事实上,java在每次进入同步方法时都会检查当前线程是否具有锁

private synchronized void oneMore()
    {
      // do something
    }
这相当于

private void oneMore(){
      synchronized(this){
      // do something
    }
}
但是因为java中的内在锁是可重入的;如果一个线程拥有锁,它不会在进入另一个同步块后重新获取它,如您的示例所示。否则,这将创建死锁

更新:在下面回答您的评论。从Java Concurrency的实践来看:

Reentrancy is implemented by associating with each lock an acquisition count 
and an owning thread. When the count is zero, the lock is considered unheld. 
When a thread acquires a previously unheld lock, the JVM records the owner 
and sets the acquisition count to one. If that same thread acquires the lock 
again, the count is incremented, and when the owning thread exits the
synchronized block, the count is decremented. When the count reaches zero, 
the lock is released.
因此,检查是否获取了锁相当于一条if语句(或多或少),即持有所属线程的变量是否等于试图获取锁的线程

但是,正如您所指出的,私有方法上不需要synchronized关键字。通常,您应该尝试删除不必要的同步,因为这通常会导致性能下降