我讀的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