这取自Joshua Bloch撰写的一本书.
我不是英语母语人士,因此有理由要求澄清疑问.
Because intrinsic locks are reentrant, if a thread tries
to acquire a lock that it already holds, the request
succeeds. Reentrancy means that locks are acquired on a
per-thread rather than **per-invocation basis.
通过每次调用,他是否意味着每个方法调用?
考虑一下片段:
class Factoriser{
public synchronized void doSomething(){
// code goes here
}
}
假设有一个线程A并且能够获取具有实例方法doSomething()的对象的锁.由于某种原因,相同的线程Thread A再次获取对同一对象实例方法doSomething()的锁定(想象一下,之前的锁还没有被释放).
如果我正确理解了约书亚的陈述,那么即使有2个方法调用/调用,也只会有一个锁.我的理解是100%正确的.请举例说明.我很困惑,因为作者在下面的段落中澄清了这一点,这进一步困扰了我.
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.
如果Reentrancy / locks获取不是基于每次调用,为什么JVM为我上面描述的场景设置的计数设置为2?
最佳答案 计数器用于匹配锁扣和粪便.仅当计数器为0时才能释放锁定.将方法foo()标记为已同步并在对象obj上调用它与以下块相同:
// calling obj.foo()
synchronized(obj) {
// Do the foo-work
}
假设我们有两个同步方法:foo()和bar(),后者从前者调用.调用将具有以下结构:
final FooBar obj = new FooBar();
// calling obj.foo()
synchronized(obj) { // 1. here the lock is acquired, the counter is set to 1
// do some foo-work
// calling obj.bar()
synchronized(obj) { // 2. the same lock object, the counter is set to 2
// do the bar-work
} // 3. the counter is set to 1, the lock is still not released
// continue doing the foo-work
} // 4. the counter is 0, the lock is released
如果没有计数器,在第3步我们将释放锁定,这将是一个错误,因为我们仍然在外部同步块中.因此,需要计数器才能正确实现重入.