【java並發】(2) Java線程同步:synchronized鎖住的是代碼還是對象

來源:互聯網
上載者:User

標籤:blog   private   關鍵字   this   thread   for   括弧   run   xtend   

在Java中,synchronized關鍵字是用來控制線程同步的,就是在多線程的環境下,控制synchronized程式碼片段不被多個線程同時執行。synchronized既可以加在一段代碼上,也可以加在方法上。

關鍵是,不要認為給方法或者程式碼片段加上synchronized就萬事大吉,看下面一段代碼:

class Sync {        public synchronized void test() {          System.out.println("test開始..");          try {              Thread.sleep(1000);          } catch (InterruptedException e) {              e.printStackTrace();          }          System.out.println("test結束..");      }  }    class MyThread extends Thread {        public void run() {          Sync sync = new Sync();          sync.test();      }  }    public class Main {        public static void main(String[] args) {          for (int i = 0; i < 3; i++) {              Thread thread = new MyThread();              thread.start();          }      }  }  

運行結果:
test開始..
test開始..
test開始..
test結束..
test結束..
test結束..

可以看出來,上面的程式起了三個線程,同時運行Sync類中的test()方法,雖然test()方法加上了synchronized,但是還是同時運行起來,貌似synchronized沒起作用。 

將test()方法上的synchronized去掉,在方法內部加上synchronized(this):

public void test() {      synchronized(this){          System.out.println("test開始..");          try {              Thread.sleep(1000);          } catch (InterruptedException e) {              e.printStackTrace();          }          System.out.println("test結束..");      }  }  

運行結果:
test開始..
test開始..
test開始..
test結束..
test結束..
test結束..

一切還是這麼平靜,沒有看到synchronized起到作用。 

實際上,synchronized(this)以及非static的synchronized方法(至於static synchronized方法請往下看),只能防止多個線程同時執行同一個對象的同步程式碼片段。

回到本文的題目上:synchronized鎖住的是代碼還是對象。答案是:synchronized鎖住的是括弧裡的對象,而不是代碼。對於非static的synchronized方法,鎖的就是對象本身也就是this。

當synchronized鎖住一個對象後,別的線程如果也想拿到這個對象的鎖,就必須等待這個線程執行完成釋放鎖,才能再次給對象加鎖,這樣才達到線程同步的目的。即使兩個不同的程式碼片段,都要鎖同一個對象,那麼這兩個程式碼片段也不能在多線程環境下同時運行。

所以我們在用synchronized關鍵字的時候,能縮小程式碼片段的範圍就盡量縮小,能在程式碼片段上加同步就不要再整個方法上加同步。這叫減小鎖的粒度,使代碼更大程度的並發。原因是基於以上的思想,鎖的程式碼片段太長了,別的線程是不是要等很久,等的花兒都謝了。當然這段是題外話,與本文核心思想並無太大關聯。

再看上面的代碼,每個線程中都new了一個Sync類的對象,也就是產生了三個Sync對象,由於不是同一個對象,所以可以多線程同時運行synchronized方法或程式碼片段。

為了驗證上述的觀點,修改一下代碼,讓三個線程使用同一個Sync的對象。

class MyThread extends Thread {        private Sync sync;        public MyThread(Sync sync) {          this.sync = sync;      }        public void run() {          sync.test();      }  }    public class Main {        public static void main(String[] args) {          Sync sync = new Sync();          for (int i = 0; i < 3; i++) {              Thread thread = new MyThread(sync);              thread.start();          }      }  }  

運行結果:
test開始..
test結束..
test開始..
test結束..
test開始..
test結束..

可以看到,此時的synchronized就起了作用。 

那麼,如果真的想鎖住這段代碼,要怎麼做?也就是,如果還是最開始的那段代碼,每個線程new一個Sync對象,怎麼才能讓test方法不會被多線程執行。 

解決也很簡單,只要鎖住同一個對象不就行了。例如,synchronized後的括弧中鎖同一個固定對象,這樣就行了。這樣是沒問題,但是,比較多的做法是讓synchronized鎖這個類對應的Class對象。

class Sync {        public void test() {          synchronized (Sync.class) {              System.out.println("test開始..");              try {                  Thread.sleep(1000);              } catch (InterruptedException e) {                  e.printStackTrace();              }              System.out.println("test結束..");          }      }  }    class MyThread extends Thread {        public void run() {          Sync sync = new Sync();          sync.test();      }  }    public class Main {        public static void main(String[] args) {          for (int i = 0; i < 3; i++) {              Thread thread = new MyThread();              thread.start();          }      }  }  

運行結果:
test開始..
test結束..
test開始..
test結束..
test開始..
test結束..

上面代碼用synchronized(Sync.class)實現了全域鎖的效果。

最後說說static synchronized方法,static方法可以直接類名加方法名調用,方法中無法使用this,所以它鎖的不是this,而是類的Class對象,所以,static synchronized方法也相當於全域鎖,相當於鎖住了程式碼片段。

 

 

轉載自:http://blog.csdn.net/xiao__gui/article/details/8188833 

【java並發】(2) Java線程同步:synchronized鎖住的是代碼還是對象

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.