线程无法获得锁定会发生什么?

时间:2010-10-18 18:34:56

标签: java locking monitor blocking

无法获取锁定(非旋转)的线程会发生什么?它进入BLOCKED状态。它是如何再次执行的?

Lock lck = new ReentrantLock();
lck.lock()
try
{
}
finally
{
   lck.unlock();
}

3 个答案:

答案 0 :(得分:4)

调度程序(或底层的Lock实现)负责让它再次运行。如果锁定操作被转换为内核中的互斥锁调用,则调度程序将不会重新调度该线程,直到互斥锁变为可用为止;那么OS调度程序将重新唤醒线程。阅读Context Switch上的维基百科页面以及其中的链接可能会更深入地了解所涉及的详细机制。您也可以直接查看ReentrantLock的代码,但最终会将您的问题归结为基本组合,包括AbstractedQueuedSynchronizer,各种原子操作,以及LockSupport.park()和{{1} }。如果您对内核级别的阻塞/上下文切换特别感兴趣,或者特别是如何在内核上实现各种Java原语(例如,unpark()或原始对象监视器),则可以扩充您的问题或者询问新问题。 / p>

实际上,由于这样做成本很高,因此可以通过JVM或锁实现对其进行优化。例如,线程实际上可能会旋转一下,看看在实际阻塞之前是否释放了锁。

请注意,即使底层操作系统线程未被阻止,Java线程也可能会报告状态BLOCKED,特别是在下面的性能白皮书中描述的自适应旋转情况中。

有一些很好的资源可以学习Java中的并发控制。领导万神殿是Java Concurrency in Practice。关于HotSpot 6.0 in the Java SE 6 Performance Whitepaper和某些related slides中同步性能的一些有趣讨论。

答案 1 :(得分:2)

锁定获取从不失败。将其视为尚未成功。

当然,在某些情况下永远不会成功,但是没有转换事件,线程会被告知失败......它只是在等待。

答案 2 :(得分:0)

持有锁的线程解锁锁定,然后(或“a”)阻塞的线程被唤醒。如果持有锁的线程永远不会释放锁(可能是因为它在另一个资源上被阻塞),那么就会出现死锁。非旋转锁通常使用wait()/ notify()原语或类似的东西,以便在锁再次可用时通知线程。