java多線程中synchronized關鍵字的用法

轉自:http://www.cdtarena.com/javapx/201308/9596.html

    由於同一進程內的多個線程共享內存空間,在Java中,就是共享實例,當多個線程試圖同時修改某個實例的內容時,就會造成衝突,因此,線程必須實現共享互斥,使多線程同步。

   最簡單的同步是將一個方法標記爲synchronized,對同一個實例來說,任一時刻只能有一個synchronized方法在執行。當一個方法正在執行某個synchronized方法時,其他線程如果想要執行這個實例的任意一個synchronized方法,都必須等待當前執行 synchronized方法的線程退出此方法後,才能依次執行。

   但是,非synchronized方法不受影響,不管當前有沒有執行synchronized方法,非synchronized方法都可以被多個線程同時執行。

   此外,必須注意,只有同一實例的synchronized方法同一時間只能被一個線程執行,不同實例的synchronized方法是可以併發的。例如,class A定義了synchronized方法sync(),則不同實例a1.sync()和a2.sync()可以同時由兩個線程來執行。

   多線程同步的實現最終依賴鎖機制。我們可以想象某一共享資源是一間屋子,每個人都是一個線程。當A希望進入房間時,他必須獲得門鎖,一旦A獲得門鎖,他進去後就立刻將門鎖上,於是B,C,D就不得不在門外等待,直到A釋放鎖出來後,B,C,D中的某一人搶到了該鎖(具體搶法依賴於 JVM的實現,可以先到先得,也可以隨機挑選),然後進屋又將門鎖上。這樣,任一時刻最多有一人在屋內(使用共享資源)。

   Java語言規範內置了對多線程的支持。對於Java程序來說,每一個對象實例都有一把"鎖",一旦某個線程獲得了該鎖,別的線程如果希望獲得該鎖,只能等待這個線程釋放鎖之後。獲得鎖的方法只有一個,就是synchronized關鍵字。例如:

   public class SharedResource {

   private int count = 0;

   public int getCount() { return count; }

   public synchronized void setCount(int count) { this.count = count; }

   }

   同步方法public synchronized void setCount(int count) { this.count = count; } 事實上相當於:

   public void setCount(int count) {

   synchronized(this) { // 在此獲得this鎖

   this.count = count;

   } // 在此釋放this鎖 http://www.cdtarena.com/ruanj.html

   }

   紅色部分表示需要同步的代碼段,該區域爲"危險區域",如果兩個以上的線程同時執行,會引發衝突,因此,要更改SharedResource的內部狀態,必須先獲得SharedResource實例的鎖。

   退出synchronized塊時,線程擁有的鎖自動釋放,於是,別的線程又可以獲取該鎖了。

   爲了提高性能,不一定要鎖定this,例如,SharedResource有兩個獨立變化的變量:成都java培訓

   public class SharedResouce {

   private int a = 0;

   private int b = 0;

   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 = 0;

   private int b = 0;

   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;

   }

   }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章