由於同壹進程內的多個線程***享內存空間 在Java中 就是***享實例 當多個線程試圖同時修改某個實例的內容時 就會造成沖突 因此 線程必須實現***享互斥 使多線程同步
最簡單的同步是將壹個方法標記為synchronized 對同壹個實例來說 任壹時刻只能有壹個synchronized方法在執行 當壹個方法正在執行某個synchronized方法時 其他線程如果想要執行這個實例的任意壹個synchronized方法 都必須等待當前執行 synchronized方法的線程退出此方法後 才能依次執行
但是 非synchronized方法不受影響 不管當前有沒有執行synchronized方法 非synchronized方法都可以被多個線程同時執行
此外 必須註意 只有同壹實例的synchronized方法同壹時間只能被壹個線程執行 不同實例的synchronized方法是可以並發的 例如 class A定義了synchronized方法sync() 則不同實例a sync()和a sync()可以同時由兩個線程來執行
多線程同步的實現最終依賴鎖機制 我們可以想象某壹***享資源是壹間屋子 每個人都是壹個線程 當A希望進入房間時 他必須獲得門鎖 壹旦A獲得門鎖 他進去後就立刻將門鎖上 於是B C D就不得不在門外等待 直到A釋放鎖出來後 B C D中的某壹人搶到了該鎖(具體搶法依賴於 JVM的實現 可以先到先得 也可以隨機挑選) 然後進屋又將門鎖上 這樣 任壹時刻最多有壹人在屋內(使用***享資源)
Java語言規範內置了對多線程的支持 對於Java程序來說 每壹個對象實例都有壹把 鎖 壹旦某個線程獲得了該鎖 別的線程如果希望獲得該鎖 只能等待這個線程釋放鎖之後 獲得鎖的方法只有壹個 就是synchronized關鍵字 例如
public class SharedResource {
private int count = ;
public int getCount() { return count; }
public synchronized void setCount(int count) { unt = count; }
}
同步方法public synchronized void setCount(int count) { unt = count; } 事實上相當於
public void setCount(int count) {
synchronized(this) { // 在此獲得this鎖
unt = count;
} // 在此釋放this鎖
}
紅色部分表示需要同步的代碼段 該區域為 危險區域 如果兩個以上的線程同時執行 會引發沖突 因此 要更改SharedResource的內部狀態 必須先獲得SharedResource實例的鎖
退出synchronized塊時 線程擁有的鎖自動釋放 於是 別的線程又可以獲取該鎖了
為了提高性能 不壹定要鎖定this 例如 SharedResource有兩個獨立變化的變量
public class SharedResouce {
private int a = ;
private int b = ;
public synchronized void setA(int a) { this a = a; }
public synchronized void setB(int b) { this b = b; }
}
若同步整個方法 則setA()的時候無法setB() setB()時無法setA() 為了提高性能 可以使用不同對象的鎖
public class SharedResouce {
private int a = ;
private int b = ;
private Object sync_a = new Object()
private Object sync_b = new Object()
public void setA(int a) {
synchronized(sync_a) {
this a = a;
}
}
public synchronized void setB(int b) {
synchronized(sync_b) {
this b = b;
}
lishixinzhi/Article/program/Java/gj/201311/27512