我读到一个用户线程可以与系统线程死锁,我的问题是,这个系统线程可以是与线程共享资源的任何线程(,而不一定是java线程)。在锁定文件后,对两个文件进行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();
}
}发布于 2013-12-07 18:21:02
如果只涉及Java对象监视器锁,那么单个Java线程不能对自己死锁,这是正确的。
您所说的“系统线程”的含义还不完全清楚。即使在运行一个简单的程序时,JVM也会有几个线程在运行,比如终结器线程,或者对于GUI应用程序,运行一个事件分发线程(EDT)。这些线程可能会对单个应用程序线程采取Java对象监视锁,从而导致死锁。
一个Java线程可以对外部进程死锁,而不是其他Java线程。例如,考虑一下这个程序:
public static void main(String[] args) throws Exception {
Process proc = Runtime.getRuntime().exec("cat");
byte[] buffer = new byte[100_000];
OutputStream out = proc.getOutputStream();
out.write(buffer);
out.close();
InputStream in = proc.getInputStream();
int count = in.read(buffer);
System.out.println(count);
}它运行"cat“,它只是从stdin复制到stdout。这个程序通常会死锁,因为它会向子进程写入大量数据。子进程将阻止对其输出的写入,因为父进程尚未读取它。这将阻止子进程读取其所有输入。因此,Java线程在子进程上陷入了僵局。(处理这种情况的通常方法是让另一个Java线程读取子进程输出。)
如果一个Java线程正在等待从未发生的通知,那么它就会死锁。考虑:
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
synchronized (obj) {
obj.wait();
}
}这个程序永远不会终止,因为没有任何东西会通知obj或中断线程。这似乎有点人为的,但这种“损失的唤醒问题”的实例确实发生在实践中。有错误的系统可能无法正确设置状态,或者在错误的时间调用notify,或者调用notify而不是notifyAll,使得wait调用中的线程被阻塞,等待永远不会发生的通知。在这种情况下,可能很难识别该线程所依赖的另一个线程,因为该线程过去可能已经死了,或者它可能还没有创建。但这肯定是僵局。
更新
我遇到了另一个单线程死锁的例子。Goetz et.第215页描述了线程饥饿死锁.考虑一个例子
提交任务并等待其结果的任务在单线程
Executor中执行。在这种情况下,第一个任务将永远等待,永久地延迟该任务和等待在该Executor中执行的所有其他任务。
(单线程Executor基本上是处理任务队列的单个线程,每次处理一个任务队列。)
更新2
在单线程死锁的文献中,我发现了另一个例子:
有三种模式的成对死锁,可以发生使用监视器。当然,在实践中,死锁通常涉及两个以上的进程,在这种情况下,观察到的实际模式往往更复杂;相反,单个进程也有可能与自身死锁(例如,如果条目过程是递归的)。
作者声明: David D. Redell.具有Mesa流程和监控的经验。CACM第23卷第2期,1980年2月。
请注意,在本文中,“进程”指的是线程,而“入口过程”就像一个同步的方法。但是,在Mesa中,监视器并不是可重入的,因此,如果单个线程再次尝试进入同一个监视器,它本身就会死锁。
Posix线程也是如此。如果一个线程在普通互斥(即不是递归)互斥上第二次调用pthread_mutex_lock,那么线程本身就会死锁。
从这些例子中,我得出结论,“死锁”并不严格地需要两个或多个线程。
发布于 2013-12-07 09:44:44
对于第一个问题:想想任何Swing应用程序。例如,主线程可能很容易干扰事件调度线程(因为所有事件处理都发生在该特定线程中)。另外,您还可以使用终结器线程。
对于第二个问题:是的,您可以按任何顺序释放锁。
https://stackoverflow.com/questions/20438186
复制相似问题