获取锁失败的线程会发生什么?

Nor*_*asu 5 java locking monitor blocking

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

Lock lck = new ReentrantLock();
lck.lock()
try
{
}
finally
{
   lck.unlock();
}
Run Code Online (Sandbox Code Playgroud)

and*_*soj 4

调度程序(或底层的 Lock 实现)负责让它再次运行。如果锁定操作一直被转换为互斥锁调用进入内核,那么调度程序将不会重新调度线程,直到互斥锁变得可用;然后操作系统调度程序将重新唤醒线程。阅读有关上下文切换的维基百科页面和那里的链接可能会更深入地了解所涉及的详细机制。您也可以直接查看代码,ReentrantLock但这最终会将您的问题归结为原语的某种组合,包括AbstractedQueuedSynchronizer、各种原子操作,也许LockSupport.park()还有 和unpark()。如果您对内核级阻塞/上下文切换特别感兴趣,或者特别对如何j.u.c.Lock在内核之上实现各种 Java 原语(例如,或原语对象监视器)感兴趣,您可能会扩充您的问题或提出一个新问题。

在实践中,由于这是昂贵的,因此可以通过 JVM 或锁实现来优化它。例如,线程实际上可能会旋转一段时间,以查看锁在实际阻塞之前是否已释放。

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

有一些很棒的资源可以帮助您了解 Java 中的并发控制。领先的万神殿是《Java 并发实践》Java SE 6 性能白皮书和一些相关幻灯片中对 HotSpot 6.0中的同步性能进行了一些有趣的讨论。