上次說到的關於執行緒帶來的競態性和記憶體可見性兩個問題,可以用synchonized關鍵字來解決。
synchonized可以用在修飾例項方法、靜態方法以及**塊。
1、例項方法
public class counter
public synchronized int getcount()
}
這樣使用多個執行緒去呼叫裡面的方法就不會存在問題了。但是需要注意的是synchronizied在這裡面同步的是物件,也就是當前的this,也就是說如果這裡有不同的物件,那他們是可以同時呼叫incr()方法的。 而且對於乙個物件來說,裡面的所有sychronized修飾的方法都要按照順序執行。
2、靜態方法
public class staticcounter
public static synchronized int getcount()
}
修飾靜態方法的時候同步的是類的物件,也就是staticcounter.class這個物件。所以如果乙個類裡面有例項的同步方法也有靜態的同步方法,因為他們修飾的是不同物件所以可以被多執行緒同時呼叫。
3、**快
public class counter
}public int getcount()
}}
這個跟例項方法前面的sychonized效果是一樣的,其實可以用任意物件來做同步鎖,因為每個物件都會有乙個鎖和乙個等待佇列。
public class counter
}public int getcount()
}}
1、可重入性
當乙個執行緒獲得了鎖以後,她可以呼叫需要同樣鎖的其它**。
2、記憶體可見性
他可以把寫入資料立馬同步到記憶體,也可以保證從記憶體裡面讀到的都是最新資料。為了保證記憶體可見性還有一種比較輕量的方法就是給變數加上修飾符volatile,也可以保證記憶體可見性的問題。
3、死鎖
public class deadlockdemo catch (interruptedexception e)
synchronized (lockb) }}
};athread.start();
}private static void startthreadb() catch (interruptedexception e)
synchronized (locka) }}
};bthread.start();
}public static void main(string args)
}
這段**就有死鎖問題,所以一般避免在持有乙個鎖的同時去申請另乙個鎖,如果確實需要多個鎖,所有**應該按照相同的順序去申請。
在下面幾種情況下就不能保證完全同步
1、復合操作,比如先檢查再更新
public class enhancedmap
public v putifabsent(k key, v value)
map.put(key, value);
return null;
}public void put(k key, v value)
}
在putifabsent方法中很可能多個執行緒都執行到old!=null這行**,這樣就有問題了。
2、偽同步
public synchronized v putifabsent(k key, v value)
map.put(key, value);
return null;
}
為了解決上面的問題,在方法上加入synchronized關鍵字,但是這樣也並不能解決同步的問題,因為這裡我們同步的物件是this,而封裝的map裡面,物件是map。所以我們需要讓他們同步乙個物件,要不把方法上都加上synchronized或者用map物件進行同步。
public v putifabsent(k key, v value)
map.put(key, value);
return null;
}}
3、迭代
在修改集合的同時,遍歷集合就會出現問題,但這個時候給集合加上synchronized方法就可以保證了。
主要學習了synchronzied關鍵字的用法特性,以及他本質同步的是物件,這點很重要。然後也學習了關於同步容器中會出現的一些問題和解決方案。所以從根本上理解多執行緒造成的影響,以及解決多執行緒的方案能讓我們掌握的更好。
注:學習資料及**片段來自老馬學程式設計。
java實現單鏈表,鞏固基礎
package test.written.examination public class singlelinkedlist public node node head,tail public singlelinkedlist public void mp else 新增在頭部 public voi...
Java基礎鞏固系列 物件流
示例 public class testobjectintoutputstream catch exception e finally catch ioexception e 物件的序列化過程,將記憶體中的物件通過objectoutputstream轉換為二進位製流,儲存在硬碟檔案中 test pu...
Java基礎鞏固系列 死鎖(DeadLock)
示例 死鎖的問題,處理執行緒同步容易出現。不同的執行緒分別占用對方需要的同步資源不放棄,都在等待對方放棄自己需要的同步資源,就形成了執行緒的死鎖 寫 時,要避免死鎖!public class testdeadlock catch interruptedexception e synchronized...