调试-Thread.State: WAITING? 这是什么意思?
调试-Thread.State: WAITING? 这是什么意思?
线程状态WAIT和线程状态BLOCKED有什么区别?
Thread.State文档中写道:
BLOCKED
处于等待监视器锁的线程处于此状态。
WAITING
无限期地等待另一个线程执行特定操作的线程处于此状态。
这并没有给我解释清楚它们之间的区别。
调试-线程状态:WAITING是什么意思?
当一个线程处于阻塞状态和等待状态时,最重要的区别是对调度器的影响。处于阻塞状态的线程正在争夺一个锁定;这个线程仍然被调度器视为需要服务的对象,可能会影响调度器关于给予运行线程多少时间的决策(以便它可以给予等待锁定的线程一个机会)。
一旦一个线程处于等待状态,它对系统的压力将被最小化,调度器不再需要担心它。线程会休眠直到收到通知。除了它占用一个操作系统线程外,它完全不参与运行。
这就是为什么使用notifyAll不是理想的选择,它会唤醒一堆以前处于休眠状态并对系统没有负载的线程,其中大部分线程将会阻塞,直到它们能够获得锁定,发现它们等待的条件不成立,然后再次进入等待状态。最好只通知那些有可能取得进展的线程。
(使用ReentrantLock而不是内部锁允许您为一个锁定设置多个条件,这样您可以确保得到通知的线程是等待特定条件的线程,在线程得到通知但无法处理它的情况下避免丢失通知的错误。)
这是因为另一个线程负责在监视对象上调用notify()吗?
:我不明白你在问什么
这是关于为什么等待线程不是调度器需要担心的原因。我想知道如果等待的线程需要的话,是否会有另一个线程负责调用notify。
:等待的线程最终会被notify唤醒。调度器会决定哪个等待的线程被通知。
你说的计数是什么,你说的自旋锁,BLOCKED并不意味着它是自旋锁。
:我没有使用那个术语。我不知道你在这里要表达什么观点。
notify
是应该用来避免这种行为的。但是只是为了让一些认为notify
总是更好的人了解。如果您的应用程序可能进入这种类似死锁的情况(如果发生这种情况,您的应用程序将无法按照您的意图工作),那么应该使用notifyAll
来避免“丢失信号”(在这里,预期的线程错过了信号,因为信号到达了其他线程而不是预期的线程)。参见stackoverflow.com/a/3186336/2859238
:好的,尝试添加一些内容来涵盖这一点。对于这种情况,似乎最好使用具有多个条件的ReentrantLock。
如何决定这些阻塞线程的优先级?
在这段内容中,我们可以看到关于线程状态的一些解释和问题。首先是关于线程状态的解释,其中提到了两种状态:BLOCKED和WAITING。
在BLOCKED状态中,一个线程即将进入一个synchronized块,但是同一个对象上已经有另一个线程在运行一个synchronized块。第一个线程必须等待第二个线程退出它的块。
在WAITING状态中,一个线程正在等待另一个线程的信号。通常是通过调用Object.wait()或Thread.join()来实现的。线程将保持在这个状态,直到另一个线程调用Object.notify()或终止。
然后提到了一个问题,是否只有线程本身才能使其进入等待状态,是否Thread-B能使Thread-A进入WAIT状态。回答是只有线程本身才能使其进入等待状态。
接下来是关于为什么要使用等待状态的解释。作者认为使用等待状态是因为不希望在等待外部动作发生之前一直循环执行sleep(100ms)。当然,我们很少直接使用Object.wait(),但使用更高级的并发构造时也会进入WAITING状态,比如锁、阻塞队列等,通常是在两个线程需要协调的情况下。
此外,还有个人经验,即等待IO的线程(例如从Socket读取)处于RUNNING状态。
最后,作者补充了一点,即当一个线程从等待状态转移到其他状态时,它必须首先进入BLOCKED状态,直到能够获取与其等待的对象相关联的锁。
根据这些解释和问题,我们可以得出以下总结:线程在进入等待状态前需要先进入BLOCKED状态,只有线程本身才能使其进入等待状态。使用等待状态的原因是为了等待外部动作的发生,避免循环执行。在并发编程中,使用等待状态是为了协调两个线程的操作。此外,线程的状态是虚拟机状态,与操作系统的线程状态无关。
我们可以得出解决方法如下:
1. 确保线程在进入等待状态前先进入BLOCKED状态,以避免竞争条件。
2. 仅在需要等待外部动作发生时才使用等待状态,避免不必要的循环执行。
3. 在并发编程中,使用等待状态来协调多个线程的操作。
4. 理解线程状态是虚拟机状态,与操作系统的线程状态无关。
当一个线程在一个对象上调用wait()
方法时,它会进入等待状态。这被称为等待状态。一旦线程进入等待状态,它需要等待其他线程在该对象上调用notify()
或notifyAll()
方法。
一旦线程被通知,它不会变为可运行状态。可能是其他线程也被通知了(使用notifyAll()
),或者第一个线程尚未完成工作,因此它仍然被阻塞,直到获得机会。这被称为阻塞状态。当一个线程试图获取一个对象的锁,而另一个线程已经持有该锁时,就会发生阻塞状态。
一旦其他线程离开,轮到这个线程时,它会从阻塞状态转移到可运行状态,然后根据JVM的线程机制选择工作并进入运行状态。
你解释得更好,因为你解释了线程如何达到这两个状态的顺序,这比只解释这两个状态有更清晰的说明(这是由"More Than Five"的回答所做的)。
对于那些想知道为什么网络上找到的大多数(全部?)状态图声称notify()/notifyAll()会导致RUNNABLE而不是BLOCKED的人来说,可以参考这个链接:stackoverflow.com/questions/28378592/…
假设只有一个线程并且在某个时间上等待;现在是否有可能线程可以直接从等待状态转到可运行状态?因为这里只有单线程,没有其他线程获取锁。
有一个带有时间参数的wait(time)方法,一旦时间到期,它将返回可运行状态。但如果没有指定时间,它将等待其他线程通知或线程被中断。
你的回答很好,但没有完全解释当你尝试获取锁时,你可以进入阻塞状态的任何时间。它不一定与信号/通知有关。