首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java中带有单个线程的死锁

问java中带有单个线程的死锁
EN

Stack Overflow用户
提问于 2013-12-07 05:53:04
回答 2查看 2.4K关注 0票数 2

我读到一个用户线程可以与系统线程死锁,我的问题是,这个系统线程可以是与线程共享资源的任何线程(,而不一定是java线程)。在锁定文件后,对两个文件进行I/O操作。因此,除非系统线程与java线程共享资源,否则它无法创建死锁。是否还有其他粗体的例子。

另一个问题:

如果有两个使用两个锁的函数,它们应该以相同的顺序锁定。但是否必须按同样的顺序释放。对于这两个函数,锁释放顺序会有所不同吗?例如:

代码语言:javascript
复制
function1() {
   try {
    lock1.lock();
    lock2.lock();
   } finally {
     lock2.unlock();
     lock1.unlock();
   }
}

function2() {
   try {
    lock1.lock();
    lock2.lock();
   } finally {
     lock1.unlock();
     lock2.unlock();
   }
}

参考链接:如果单个用户线程死锁,则还必须涉及系统线程。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-07 18:21:02

如果只涉及Java对象监视器锁,那么单个Java线程不能对自己死锁,这是正确的。

您所说的“系统线程”的含义还不完全清楚。即使在运行一个简单的程序时,JVM也会有几个线程在运行,比如终结器线程,或者对于GUI应用程序,运行一个事件分发线程(EDT)。这些线程可能会对单个应用程序线程采取Java对象监视锁,从而导致死锁。

一个Java线程可以对外部进程死锁,而不是其他Java线程。例如,考虑一下这个程序:

代码语言:javascript
复制
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线程正在等待从未发生的通知,那么它就会死锁。考虑:

代码语言:javascript
复制
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,那么线程本身就会死锁。

从这些例子中,我得出结论,“死锁”并不严格地需要两个或多个线程。

票数 3
EN

Stack Overflow用户

发布于 2013-12-07 09:44:44

对于第一个问题:想想任何Swing应用程序。例如,主线程可能很容易干扰事件调度线程(因为所有事件处理都发生在该特定线程中)。另外,您还可以使用终结器线程。

对于第二个问题:是的,您可以按任何顺序释放锁。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20438186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档