java中单线程的多线程死锁
我读到单个用户线程可以与系统线程死锁强> 我的问题是,这个系统线程可以是任何与java线程共享资源的线程(不一定是java线程)。例如:锁定文件后对2个文件进行I/O操作。 因此,除非系统线程与java线程共享资源,否则它无法创建死锁。 是否有任何其他粗体的上述声明的例子
另一个问题:
如果有两个函数使用两个锁,则它们应以相同的顺序锁定。但是否必须以相同的相反顺序发布。两个功能的锁释放顺序是否不同 例如:
function1() {
try {
lock1.lock();
lock2.lock();
} finally {
lock2.unlock();
lock1.unlock();
}
}
function2() {
try {
lock1.lock();
lock2.lock();
} finally {
lock1.unlock();
lock2.unlock();
}
}
参考链接:if a single user thread deadlocks, a system thread must also be involved
# 1 楼答案
对于第一个问题:考虑任何Swing应用程序。例如,主线程可能很容易干扰事件分派线程(因为所有事件处理都发生在该特定线程中)。此外,您还可以使用终结器线程
对于第二个问题:是的,您可以按任何顺序释放锁
# 2 楼答案
如果只涉及Java对象监视器锁,那么单个Java线程就不能对自身进行死锁,这是正确的
现在还不完全清楚“系统线程”是什么意思。即使在运行一个简单的程序时,JVM也会有多个线程在运行,例如终结器线程,或者对于GUI应用程序,有一个事件分发线程(EDT)。这些线程可能会获得Java对象监视器锁,因此会针对单个应用程序线程死锁
单个Java线程可以针对外部进程死锁,而不是其他Java线程。例如,考虑这个程序:
这运行“cat”,它只是从stdin复制到stdout。这个程序通常会死锁,因为它会向子进程写入大量数据。子进程将阻止写入其输出,因为父进程尚未读取它。这会阻止子进程读取其所有输入。因此,Java线程与子进程之间出现了死锁。(处理这种情况的通常方法是让另一个Java线程读取子进程输出。)
如果一个Java线程正在等待一个永远不会发生的通知,那么它可能会死锁。考虑:
这个程序永远不会终止,因为没有任何东西会通知obj或中断线程。这似乎有点做作,但在实践中确实会出现这种“唤醒丢失问题”。有bug的系统可能无法正确设置状态,或者在错误的时间调用
notify
,或者调用notify
而不是notifyAll
,导致线程在wait
调用中被阻塞,等待永远不会发生的通知。在这种情况下,可能很难识别该线程死锁的另一个线程,因为该线程可能在过去已死亡,或者可能尚未创建。但这肯定是僵局更新
我遇到了另一个单线程死锁的例子。Goetz等人,Java并发在实践中第215页,描述了线程饥饿死锁。考虑一个例子:
(单线程
Executor
基本上是一个单线程,一次处理一个任务队列。)更新2
我在文献中发现了另一个单线程死锁的例子:
兰普森、巴特勒·W.和大卫·D·雷德尔在Mesa中使用流程和监控器的经验CACM第23卷第2期,1980年2月
请注意,在本文中,“进程”指的是我们所说的线程,“进入过程”类似于同步方法。然而,在Mesa中,监视器不是可重入的,因此如果一个线程试图再次进入同一个监视器,它可能会死锁
Posix线程也是如此。如果一个线程在一个正常(即非递归)互斥体上第二次调用
pthread_mutex_lock
,该线程将在自身上死锁从这些例子中,我得出结论,“死锁”并不严格要求两个或更多线程