Object#wait()
方法具有一个有趣的属性,它允许其他线程在被阻止的同时进入其同步块。示例(假设线程1首先运行):
线程1:
synchronized(someLock)
{
wait();
}
线程2:
synchronized(someLock)
{
notify();
}
线程2能够唤醒线程1的事实意味着,即使某个其他线程位于同一对象上的同步块中,线程2也进入了同步块。对我来说很好,但是我想知道这是否仅发生在Object#wait()
或所有使线程“等待”(Thread#sleep, Thread#join
)的方法上。就我而言,我关心Thread#join
,因为如果行为与Object#wait()
相同,则会破坏我的代码:
private void waitForClose()
{
try
{
// if one thread is waiting in join the other will wait on the semaphore
synchronized(joinLock)
{
if(outputThread != null && Thread.currentThread() != outputThread)
outputThread.join();
outputThread = null;
if(inputThread != null && Thread.currentThread() != inputThread)
inputThread.join();
inputThread = null;
}
}
catch(InterruptedException ex)
{
logger.error("Interrupted Exception while waiting for thread to join in " + name, ex);
}
}
那么由于加入调用使线程处于等待状态,多个线程是否有可能进入此同步块?
答案 0 :(得分:2)
首先,wait
和notify
机制并不是很有趣。这是在Java中协调两个或多个线程的最基本的方法。了解这里发生的事情很重要:
线程1:
synchronized (someLock) {
System.out.println("Thread 1 going to wait ...");
someLock.wait();
System.out.println("Threads 1 got notified.");
}
线程2:
synchronized (someLock) {
System.out.println("Notifying");
someLock.notify();
System.out.println("Exiting block.");
}
wait()
调用将放弃该锁,允许另一个线程抓住它。此时,线程1将无法继续进行,即使它得到通知。该文档明确指出:
被唤醒的线程要等到当前 线程放弃了对该对象的锁定。
因此,只有在线程2退出synchronized
块之后,线程1才会继续执行wait()
之后的代码。
Thread.join()
是语法糖,是一种辅助方法,在引擎盖下使用相同的wait
和notify
/ notifyAll()
方法。实际上,javadoc警告不要在wait
对象上使用notify
和Thread
,以免干扰此机制。
此实现使用this.wait循环作为条件 这还活着。当线程终止时,this.notifyAll方法是 调用。建议应用程序不要使用等待,通知或 线程实例上的notifyAll。
Thread.sleep()
与wait
和notify
无关。它不需要对象的锁,也不需要位于synchronized
块中。
您的代码似乎正在joinLock
对象上同步,而outputThread.join()
将在outputThread
对象上同步并等待。它们是无关的。如果outputThread
在joinLock
上进行同步,则可能会有死锁的危险。没有outputThread
的代码,我不能说。