如下面的示例所示,一旦用call
方法对某个对象进行了锁定,就无需使用其他方法来生成synchronized
个关键字。
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在这种情况下的表现如何,我不确定,但我认为它与偏见锁定不同。
答案 0 :(得分:4)
实际上,java会在每次进入同步方法时检查当前线程是否具有锁定。
private synchronized void oneMore()
{
// do something
}
这相当于
private void oneMore(){
synchronized(this){
// do something
}
}
但是因为java中的内部锁是可重入的;如果一个线程有锁,一旦它进入另一个同步块,它就不会重新获取它,如你的例子所示。否则,这将造成死锁。
更新:在下面回答您的评论。来自Java Concurency的实践:
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关键字。通常,您应该尝试删除不必要的同步,因为这通常会导致性能下降。