首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java,子进程和未读输出流:什么时候死锁?

问Java,子进程和未读输出流:什么时候死锁?
EN

Stack Overflow用户
提问于 2012-02-21 15:43:59
回答 2查看 1.4K关注 0票数 2

当使用Runtime.exec()在java中创建子进程时,我意识到必须填充输入/排出输出流,以防止子进程阻塞。

有趣的是,Process的javadoc声明了更多:

代码语言:javascript
复制
...failure to promptly write the input stream or read the output stream of
the subprocess may cause the subprocess to block, and even deadlock.

我想知道,在这种情况下,子进程可以也死锁!

问题:

  1. 在什么情况下会陷入僵局?
  2. 为什么会陷入僵局?
  3. 您能提供一个显示此死锁的简短示例程序吗?
  4. 这个死锁在操作系统中是个bug吗?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-12-19 03:11:45

当父程序试图在读取任何输出之前将太多数据发送到其子流的输入流时,可能会出现死锁。

请考虑以下代码:

代码语言:javascript
复制
final int LINES = 10;
// "tr" is a Unix command that translates characters;
// Here, for every line it reads, it will output a line with
// every 'a' character converted to 'A'.  But any command that outputs
// something for every line it reads (like 'cat') will work here
Process p = Runtime.getRuntime().exec("tr a A");
Writer out = new OutputStreamWriter(p.getOutputStream());
for (int i = 0; i < LINES; i++) {
    out.write("abcdefghijklmnopqrstuvwxyz\n");
}
out.close();
// Read all the output from the process and write it to stdout
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
    System.out.println(line);
}

对于lines的小值,它将很好地工作;在我们开始读取它之前,tr的所有输出都可以放在OS缓冲区中。但是,对于较大的值(>10000应该足够),OS缓冲区将被填满;在tr命令中,对write的调用将被阻塞,等待缓冲区被耗尽,反过来,Java代码所写入的缓冲区将被填满(因为tr被阻塞,从而阻止它从输入中读取),从而阻止我们对out.write的调用,从而导致一个死锁,其中两个进程都在等待写入没有被主动读取的完整缓冲区。

这种死锁在操作系统中不是一个缺陷,因为有限的进程间通信缓冲区大小是精心设计的决定。可供选择的(无限缓冲区大小)有一些缺点:

  • 可以耗尽内核内存
  • 为了避免上述情况,如果缓冲区自动“溢出”到磁盘,则可能导致不可预测的性能,并可能填满磁盘。

顺便说一下,死锁也可能由于进程内缓冲区而发生.假设为了解决上面的死锁,我们将Java代码更改为编写一行,然后交替读取一行。然而,Linux进程在不直接写入终端时不刷新每一行是很常见的.因此,tr可能读取一行,并将其写入其libc输出缓冲区,而不是阻止等待写入下一行--我们的tr代码将阻止等待tr输出一行。

票数 3
EN

Stack Overflow用户

发布于 2012-02-21 15:48:40

死锁涉及始终至少有两个参与者。因此,可能死锁的并不仅仅是子进程,而是父进程和子进程的组合。

举个例子:

Subprocess想要读取一行,处理它并打印结果。父进程认为它可以先读取子进程的输出,然后才提供输入。

结果:死锁,两个进程都在等待另一个进程的输入。

因此,不,这不是操作系统中的错误,而是(父进程)中的逻辑错误。

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

https://stackoverflow.com/questions/9380466

复制
相关文章

相似问题

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