java - Thread#join() 是否让其他线程通过同步块?
问题描述
该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);
}
}
那么是否有可能多个线程进入这个同步块,因为加入调用使线程处于等待状态?
解决方案
首先,wait
andnotify
机制并不是那么有趣。它是在 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
and notify
/notifyAll()
方法。事实上,javadoc警告不要在对象上使用wait
和,不要干扰这种机制。notify
Thread
此实现使用以 this.isAlive 为条件的 this.wait 调用循环。当线程终止时,将调用 this.notifyAll 方法。建议应用程序不要在 Thread 实例上使用 wait、notify 或 notifyAll。
Thread.sleep()
wait
与和无关notify
。它不需要对象的锁,也不需要在synchronized
块中。
您的代码似乎正在同步一个调用的对象joinLock
,而outputThread.join()
将同步并等待该outputThread
对象。他们是无关的。outputThread
如果正在同步,您可能会面临死锁的风险joinLock
。没有outputThread
我不能说的代码。
推荐阅读
- php - PHP $_POST[][] 二维数组到 json_encode 添加额外的单引号
- python - 如何绘制条形图,显示按年份分组的每个月的平均每日值?
- python - 好吧,这很奇怪 Python
- python - 从完整列表生成 Dayfiles
- css - flexbox width 100% 不覆盖整个页面宽度
- typescript - jest mock 没有看到它在函数中的 if 语句中被调用
- python - “列表索引必须是整数或切片,而不是 str”试图读取 json
- flutter - 在 Flutter 中实现卡片翻转动画
- html - 基于真假在同一个模板中应用CSS类的最佳方式
- powershell - Powershell更改所有文件夹和子文件夹中快捷方式的路径