我读的Java并发的话题,这里就是作者写道:在Java中死锁(用一个例子)
因为的addListener()的removeListener(),和的UpdateProgress()都是同步的, 多个线程可以调用它们而不用踩在彼此的脚趾上。但是 这个代码中潜伏着一个陷阱,可能会导致死锁,即使只有一个锁使用了 。 问题是,updateProgress()调用一个外来方法 - 它知道 没有关系的方法。该方法可以做任何事情,包括获得另一个锁定。如果是这样,那么我们已经获得了两把锁,却不知道我们是否按照正确的顺序完成了 。正如我们刚刚看到的那样,这可能导致僵局。
能否请您解释一下,我们如何能够以错误的顺序获得两把锁,如果我们总是获得放在第一位第一锁定(作为方法的UpdateProgress是同步的!),这意味着从两个锁第二作者谈到将永远被收购在第二位?
class Downloader extends Thread {
private InputStream in;
private OutputStream out;
private ArrayList<ProgressListener> listeners;
public Downloader(URL url, String outputFilename) throws IOException {
in = url.openConnection().getInputStream();
out = new FileOutputStream(outputFilename);
listeners = new ArrayList<ProgressListener>();
}
public synchronized void addListener(ProgressListener listener) {
listeners.add(listener);
}
public synchronized void removeListener(ProgressListener listener) {
listeners.remove(listener);
}
private synchronized void updateProgress(int n) {
for (ProgressListener listener : listeners)
listener.onProgress(n);
}
public void run() {
int n = 0, total = 0;
byte[] buffer = new byte[1024];
try {
while ((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
total += n;
updateProgress(total);
}
out.flush();
} catch (IOException e) {
}
}
}
谢谢。 “监听器调用”动作发生在单独的线程中(即线程3,线程4与线程1,2并行),还是发生在监听器的onProgress()方法中? – CoolOne
好吧,两者。它发生在侦听器的'onProgress()'方法中,但是请记住有_two_侦听器,每个侦听器都在独立线程上调用onProgress。在thread1上调用dlA的监听器(通过在thread1上调用的dlA.updateProgress中的listener.onProgress(n)调用),并且在thread2上调用dlB的监听器。但是,你甚至可以用_one_ listener来完成这个工作,它将自己从dlA和dlB中移除。 – yshavit
我稍微更新了答案,以显示只有一个听众会发生什么情况。 – yshavit