標籤:yacc eth 活躍 target from art 爭奪 not 資訊
一、死結所謂死結: 是指兩個或兩個以上的進程在運行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。
百科百科
當兩個以上的運算單元,兩方都在等待對方停止執行,以取得系統資源,可是沒有一方提前退出時。這樣的狀況。就稱為死結。維基百科
1. 順序死結最少有兩個鎖。一個線程擷取到A鎖須要擷取B鎖才幹進行操作,而另外一個線程擷取到了B鎖,須要擷取A鎖才幹運行操作,這樣的情況下easy出現順序死結。
public class LeftRightDeadlock {private final Object left = new Object();private final Object right = new Object();public void leftRight() {synchronized (left) {synchronized (right) {// doSomething();}}}public void rightLeft() {synchronized (right) {synchronized (left) {// doSomething();}}}}
2. 動態鎖順序死結
public void transferMoney(Account fromAccount, Account toAccount, DollarAmount anount)throws InsufficientResourcesException {synchronized (fromAccount) {synchronized (toAccount) {if (fromAccount.getBalance().compareTo(amount) < 0) {throw new InsufficientResourcesException();} else {fromAccount.debit(anount);toAccount.credit(anount);}}}}
A: transferMoney(myAccount, yourAccount, 10);
B: transferMoney(yourAccount, myAccount, 20);
由外部傳入的變數全部鎖的條件,可是由以上傳入的變數能夠看到,這樣的情況下會出現一個線程先擷取myAccount鎖在申請yourAccount鎖,而另外一個線程相反先擷取yourAccount鎖在申請myAccount鎖。
private static final Object tieLock = new Object();public void transferMoney(final Account fromAccount, final Account toAccount, final DollarAmount anount)throws InsufficientResourcesException {class Helper{ public void transfer() throws InsufficientResourcesException { if (fromAccount.getBalance().compareTo(amount) < 0){ throw new InsufficientResourcesException(); } else{fromAccount.debit(anount);toAccount.credit(anount); } }}int fromHash = System.identityHashCode(fromAccount);int toHash = System.identityHashCode(toAccount);if (fromHash < toHash){ synchronized (fromAccount){ synchronized (toAccount) { new Helper().transfer(); } }} else if (fromHash > toHash){ synchronized (toAccount){ synchronized (fromAccount) { new Helper().transfer(); } }} else { synchronized (tieLock) { synchronized (fromAccount) { synchronized (toAccount) { new Helper().transfer(); } } }}}
3. 在協作對象之間發生的死結
class Taxi {private Point location, destination;private final Dispatcher dispatcher;public Taxi(Dispatcher dispatcher) { this.dispatcher = dispatcher;}public synchronized Point getLocation(){ return location;}public synchronized void setLocation(Point location){ this.location = location; if (location.equals(destination)){ dispatcher.notifyAvaliable(this); }}} class Dispatcher {private final Set<Taxi> taxis;private final Set<Taxi> avaliableTaxis;public Dispatcher(){ taxis = new HashSet<Taxi>(); avaliableTaxis = new HashSet<Taxi>();}public synchronized void notifyAvaliable(Taxi taxi) { avaliableTaxis.add(taxi);}public synchronized Image getImage(){ Image image = new Image(); for (Taxi t :taxis){ image.drawMarker(t.getLocation()); } return image;}}
4. 開放調用 -- 待填充
5. 資源死結外部鎖常被忽視而導致死結,比如資料庫的鎖
二、死結的避免與診斷1. 支援定時的死結存在一些預防死結的手段。比方Lock的tryLock,JDK 7中引入的Phaser等。
2. 通過線程轉儲資訊來分析死結通過Dump線程的StackTrace,比如linux下運行命令 kill -3 <pid>,或者jstack –l <pid>,或者使用Jconsole串連上去查看線程的StackTrace。由此來診斷死結問題。
三、其它活躍性危急1. 饑餓2. 糟糕的響應性3. 活鎖
四、鎖的使用使用支援CAS的資料結構。避免使用鎖,如:AtomicXXX、ConcurrentMap、CopyOnWriteList、ConcurrentLinkedQueue死結常常是無法全然避免的,鴕鳥策略被非常多基礎架構所採用。存在檢測死結的辦法
五、參考資料:《溫紹錦 - Java並發程式設計教程》
《Java並發編程實戰》第十章 避免活躍性危急 讀書筆記