Java 线程、锁和条件的状态

Java 线程、锁和条件的状态,java,multithreading,locking,synchronized,reentrantlock,Java,Multithreading,Locking,Synchronized,Reentrantlock,在Java中,如果一个线程t2,试图从synchronized获得一个锁,该锁当前正被另一个线程t1使用,那么t2将从runnable切换到blocked。对的如何使用ReentrantLocks 如果线程t1使用完锁,那么t2会自动切换回runnable还是需要使用notifyAll()?如何使用无条件的ReentrantLock用法。如果不使用条件,如何通知线程t2它应该切换回runnable?使用无条件重入锁是否明智,甚至可能 如果这个问题已经得到了回答(我找不到),如果您能将其链接到我,

在Java中,如果一个线程
t2
,试图从synchronized获得一个锁,该锁当前正被另一个线程
t1
使用,那么
t2
将从runnable切换到blocked。对的如何使用
ReentrantLock
s

如果线程
t1
使用完锁,那么
t2
会自动切换回runnable还是需要使用
notifyAll()
?如何使用无条件的
ReentrantLock
用法。如果不使用条件,如何通知线程
t2
它应该切换回runnable?使用无条件重入锁是否明智,甚至可能


如果这个问题已经得到了回答(我找不到),如果您能将其链接到我,我将不胜感激。

听起来您混淆了阻塞和等待状态。阻塞意味着线程正在尝试获取锁,但无法获取,因此被卡住。等待意味着线程处于休眠状态;它一直挂起,直到它收到通知,或者直到它从等待中返回(超时,如果使用超时值调用,或者虚假唤醒)

一旦锁可用,OS调度程序就必须决定哪个被阻止的线程获得它。它为获取锁而选择的线程将成为可运行线程

所以notify属于等待线程,而不是阻塞线程。一个线程拥有锁,但发现它无法继续(它检测到它等待的条件不正确)可以调用该锁上的wait,释放锁并进入休眠状态。您可以使用notify命令调度程序唤醒正在等待锁的任何一个线程。一旦线程被唤醒,它必须重新获得它先前释放的锁,然后才能退出wait方法


ReentrantLock的基本行为类似于内部锁,不同的是,您可以使用可重入锁具有多个条件。请记住,ReentrantLock有自己单独的调用方法(wait和signal,而不是wait和notify)。当您希望线程等待并得到通知时,可以使用ReentrantLock的条件,使用不同的条件,这样线程将只在与它们相关的条件下等待。

如果线程t2尝试在另一个线程t1当前正在使用的锁上进行同步-例如,当t1已经在同一锁上的同步块中时,尝试进入同步块-则t2将阻塞,是。可重入锁也是如此,包括
ReentrantLock
类;应该注意的是,默认锁在Java中是可重入的(稍后将对此进行详细介绍)

如果t1释放默认锁,例如通过退出同步块,则t2被解锁;这是该语言的一个特点。但是,如果您使用的是ReentrantLock,那么持有锁的线程必须显式调用
ReentrantLock.unlock()
来释放锁,就像它必须调用
ReentrantLock.lock()
来获得锁一样


请注意,“可重入”是指单个线程是否可以“重入”同步块,而不是指线程之间的任何交互。可重入锁可以由已经持有锁的线程再次锁定;不能使用非进入锁。请注意,在Java中,如果单个线程多次获得可重入锁,那么它必须释放锁相同的次数,然后等待锁的其他线程才能解锁。对于默认锁,嵌套的同步块自然会发生这种情况,可能是在不同的函数调用级别。

我想他只是用术语“runnable”来表示“waiting”。我的困惑来自我正在读的书(Cay s.Horstmann的面向对象的设计和模式)。在这本书中可以读到以下内容。这是一种简化还是我遗漏了什么?@erikp对我来说似乎是一种简化-参考@erikp,另请参阅JLS的相关章节:-17.1中处理阻塞,而17.1中处理等待和通知。2@erik:此图表可用于显示计划程序的角色。它确实简化了事情,我认为你不打算把它作为从一个州过渡到另一个州的路线图,尽管我知道你是如何得到这个想法的。