併發應用程序及時執行的能力被稱爲其活性,本節描述了最多見的活性問題,死鎖,並繼續簡要描述其餘兩個活性問題,飢餓和活鎖。java
死鎖描述了兩個或多個線程永遠被阻塞,等待彼此的狀況,這是一個例子。git
Alphonse和Gaston是朋友,是禮貌的忠實信徒,禮貌的一個嚴格規則是,當你向朋友鞠躬時,你必須一直鞠躬,直到你的朋友有機會還禮,不幸的是,這條規則沒有考慮到兩個朋友可能同時互相鞠躬的可能性,這個示例應用程序Deadlock模擬了這種可能性:github
public class Deadlock { static class Friend { private final String name; public Friend(String name) { this.name = name; } public String getName() { return this.name; } public synchronized void bow(Friend bower) { System.out.format("%s: %s" + " has bowed to me!%n", this.name, bower.getName()); bower.bowBack(this); } public synchronized void bowBack(Friend bower) { System.out.format("%s: %s" + " has bowed back to me!%n", this.name, bower.getName()); } } public static void main(String[] args) { final Friend alphonse = new Friend("Alphonse"); final Friend gaston = new Friend("Gaston"); new Thread(new Runnable() { public void run() { alphonse.bow(gaston); } }).start(); new Thread(new Runnable() { public void run() { gaston.bow(alphonse); } }).start(); } }
當Deadlock
運行時,兩個線程在嘗試調用bowBack
時極有可能會阻塞,兩個阻塞都不會結束,由於每一個線程都在等待另外一個線程退出bow
。segmentfault
飢餓和活鎖問題遠沒有死鎖常見,但仍然是每一個併發軟件設計人員可能遇到的問題。併發
飢餓描述了一種狀況,即線程沒法得到對共享資源的按期訪問,而且沒法取得進展,當「貪婪」線程使共享資源長時間不可用時會發生這種狀況。例如,假設一個對象提供了一個一般須要很長時間才能返回的同步方法,若是一個線程頻繁地調用此方法,其餘也須要頻繁同步訪問同一對象的線程將常常被阻塞。this
一個線程常常響應另外一個線程的操做,若是另外一個線程的操做也是對另外一個線程的操做的響應,則可能致使活鎖。與死鎖同樣,活鎖線程沒法取得進一步進展,可是,線程不會被阻塞 — 它們只是太忙於迴應彼此而沒法繼續工做。這至關於兩個試圖在走廊裏互相經過的人:Alphonse向左移動讓Gaston經過,而Gaston向右移動讓Alphonse經過,看到他們仍然互相阻塞,Alphone向右移動,而Gaston向左移動,他們還在互相阻塞,因此...。線程