java線程同步: synchronized詳解

來源:互聯網
上載者:User

標籤:--   logs   round   inner   bsp   highlight   div   關鍵字   start   

Java語言的關鍵字,當它用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多隻有一個線程執行該段代碼。

     一、當兩個並發線程訪問同一個對象object的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行(如果多個線程調用同一個線程,只能有一個線程得到執行)另一個線程必須等待當前線程執行完這個代碼塊以後才能執行該代碼塊

     二、然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。

     三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞

     四、第三個例子同樣適用其它同步代碼塊。也就是說,當一個線程訪問object的一個synchronized(this)同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞

     五、以上規則對其它對象鎖同樣適用.

 

舉例說明:  
 一、當兩個並發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以後才能執行該代碼塊。

package ths;public class Thread1 implements Runnable {       public void run() {            synchronized(this) {                 for (int i = 0; i < 5; i++) {                      System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);                 }            }       }       public static void main(String[] args) {            Thread1 t1 = new Thread1();            Thread ta = new Thread(t1, "A");            Thread tb = new Thread(t1, "B");            ta.start();            tb.start();       } }

結果:  

    A synchronized loop 0       A synchronized loop 1       A synchronized loop 2       A synchronized loop 3       A synchronized loop 4       B synchronized loop 0       B synchronized loop 1       B synchronized loop 2       B synchronized loop 3       B synchronized loop 4

     二、然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。

package ths;public class Thread2 {       public void m4t1() {            synchronized(this) {                 int i = 5;                 while( i-- > 0) {                      System.out.println(Thread.currentThread().getName() + " : " + i);                      try {                           Thread.sleep(500);                      } catch (InterruptedException ie) {                      }                 }            }       }       public void m4t2() {            int i = 5;            while( i-- > 0) {                 System.out.println(Thread.currentThread().getName() + " : " + i);                 try {                      Thread.sleep(500);                 } catch (InterruptedException ie) {                 }            }       }       public static void main(String[] args) {            final Thread2 myt2 = new Thread2();            Thread t1 = new Thread(  new Runnable() {  public void run() {  myt2.m4t1();  }  }, "t1"  );            Thread t2 = new Thread(  new Runnable() {  public void run() { myt2.m4t2();   }  }, "t2"  );            t1.start();            t2.start();       } }

結果:  

    t1 : 4       t2 : 4       t1 : 3       t2 : 3       t1 : 2       t2 : 2       t1 : 1       t2 : 1       t1 : 0       t2 : 0

     三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

     //修改Thread2.m4t2()方法:  

 public void m4t2() {            synchronized(this) {                 int i = 5;                 while( i-- > 0) {                      System.out.println(Thread.currentThread().getName() + " : " + i);                      try {                           Thread.sleep(500);                      } catch (InterruptedException ie) {                      }                 }            }     }

結果:

   t1 : 4       t1 : 3       t1 : 2       t1 : 1       t1 : 0       t2 : 4       t2 : 3       t2 : 2       t2 : 1       t2 : 0

     四、第三個例子同樣適用其它同步代碼塊。也就是說,當一個線程訪問object的一個synchronized(this)同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞。

     //修改Thread2.m4t2()方法如下:

 public synchronized void m4t2() {            int i = 5;            while( i-- > 0) {                 System.out.println(Thread.currentThread().getName() + " : " + i);                 try {                      Thread.sleep(500);                 } catch (InterruptedException ie) {                 }            }       }

結果:  

  t1 : 4       t1 : 3       t1 : 2       t1 : 1       t1 : 0       t2 : 4       t2 : 3       t2 : 2       t2 : 1       t2 : 0

     五、以上規則對其它對象鎖同樣適用:

package ths;
public class Thread3 { class Inner { private void m4t1() { int i = 5; while(i-- > 0) { System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i); try { Thread.sleep(500); } catch(InterruptedException ie) { } } } private void m4t2() { int i = 5; while(i-- > 0) { System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); try { Thread.sleep(500); } catch(InterruptedException ie) { } } } } private void m4t1(Inner inner) { synchronized(inner) { //使用對象鎖 inner.m4t1(); } private void m4t2(Inner inner) { inner.m4t2(); } public static void main(String[] args) { final Thread3 myt3 = new Thread3(); final Inner inner = myt3.new Inner(); Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");    Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");    t1.start();    t2.start(); } }

結果:

儘管線程t1獲得了對Inner的對象鎖,但由於線程t2訪問的是同一個Inner中的非同步部分。所以兩個線程互不干擾

  t1 : Inner.m4t1()=4       t2 : Inner.m4t2()=4       t1 : Inner.m4t1()=3       t2 : Inner.m4t2()=3       t1 : Inner.m4t1()=2       t2 : Inner.m4t2()=2       t1 : Inner.m4t1()=1       t2 : Inner.m4t2()=1       t1 : Inner.m4t1()=0       t2 : Inner.m4t2()=0

現在在Inner.m4t2()前面加上synchronized:

 private synchronized void m4t2() {            int i = 5;            while(i-- > 0) {                 System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);                 try {                      Thread.sleep(500);                 } catch(InterruptedException ie) {                 }            }       }

結果:

儘管線程t1與t2訪問了同一個Inner對象中兩個毫不相關的部分,但因為t1先獲得了對Inner的對象鎖,所以t2對Inner.m4t2()的訪問也被阻塞,因為m4t2()是Inner中的一個同步方法。

 t1 : Inner.m4t1()=4       t1 : Inner.m4t1()=3       t1 : Inner.m4t1()=2       t1 : Inner.m4t1()=1       t1 : Inner.m4t1()=0       t2 : Inner.m4t2()=4       t2 : Inner.m4t2()=3       t2 : Inner.m4t2()=2       t2 : Inner.m4t2()=1       t2 : Inner.m4t2()=0

 

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.