我已经研究了Java内部很长一段时间了。我很想学习并理解Java中的线程/锁定是如何发生的。
因此,为了访问同步方法或同步块,线程必须首先获取对象的锁定。那么,现在,我需要更多的光。
因此,每当线程获取对象的锁定时,它是否在内部增加信号量的值? 如果答案是肯定的,那么让我们来看看这个场景。
class ABC{
public void method_1(){
synchronized(xyz){
....
}
}
public void method_2(){
...
synchronized(xyz){
....
}
}
}
所以,假设有两个线程:Threaad 1和Thread 2.假设, Thread1 首先输入method_1,因此首先获得了对xyz的锁定。而且,现在说, Thread2 进入method_2并尝试获取xyz上的锁定。会发生什么? (对我来说,Thread2会被阻止,因为它发现对象的信号量值> 0)
如果我的推理是正确的,请告诉我。
答案 0 :(得分:1)
每当线程获取对象的锁定时,它是否在内部递增信号量的值?
具体实现,但不太可能,因为每次锁只能获得一次,所以不需要计数器。一个简单的切换就行了。我假设每个锁都拥有对拥有它的线程的引用(或null)。
更新:实际上,它比这复杂得多。锁还需要维护一个等待它的线程列表。此外,线程可以通过等待/通知机制暂时释放锁(因此毕竟会有一个输入计数器)。最重要的是,锁管理对性能有很大影响,因此存在各种优化。我发现这个interesting blog是由正在进行JVM锁定的人发现的。{/ p>
所以,假设有两个线程:Threaad 1和Thread 2.假设,Thread1首先进入method_1,因此首先获得了对xyz的锁定。而且,现在说,Thread2进入method_2并尝试获取xyz上的锁。会发生什么?
是的,线程2将被阻止,并等到它最终可以获得锁定。
答案 1 :(得分:1)
你的推理大致正确。线程2将被阻止,并将保持阻塞状态,直到(至少)Thread1释放互斥锁。
然而,通常不使用具有简单计数器的传统信号量来实现锁定。通常,如果对象被重新锁定(例如,如果Thread1在已经保持对该对象的锁定时尝试锁定xyz
)或存在争用时,则只有一个锁定位才会“膨胀”为完全锁定用于锁定(例如,当Thread1将其锁定时,Thread2尝试锁定xyz
)。
但是你不需要关心Java锁的实现细节......除非你自己实现JVM!
答案 2 :(得分:1)
其他答案几乎已经回答了你的问题,但为了进一步阅读,我建议: Java Concurrency In Practice