欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長資訊網(wǎng)
          最全最豐富的資訊網(wǎng)站

          一起看看synchronized的4個特性

          一起看看synchronized的4個特性

          1. synchronized鎖重入

          1.1 介紹

          關(guān)鍵字synchronized擁有鎖重入的功能,也就是在使用synchronized時,當(dāng)一個線程得到一個對象鎖后,再次請求此對象鎖時是可以再次得到該對象的鎖的。這說明在一個synchronized方法/塊內(nèi)部調(diào)用本類的其他synchronized方法/塊時,是永遠可以得到鎖的。

          例如:

          public class Service1 {      public synchronized void method1(){         System.out.println("method1");         method2();     }      public synchronized void method2(){         System.out.println("method2");         method3();     }      public synchronized void method3(){         System.out.println("method3");     }  }
          public class MyThread extends Thread {      @Override     public void run(){         Service1 service1 = new Service1();         service1.method1();     }       public static void main(String[] args) {         MyThread myThread = new MyThread();         myThread.start();     } }

          運行結(jié)果如下:
          一起看看synchronized的4個特性
          ☹ 看到這個結(jié)果的時候是茫然了,怎么就證明是可重入鎖的了呢?
          ? “可重入鎖”的概念是:自己可以再次獲取自己的內(nèi)部鎖,比如有1個線程獲得了某個對象的鎖,此時這個對象鎖還沒有釋放,當(dāng)其再次想要獲取這個對象的鎖的時候還是可以獲取的,如果不可鎖重入的話,就會造成死鎖。
          ? “可重入鎖”的最大作用就是避免死鎖

          1.2 分析

          我們知道,在程序中,是無法顯式釋放對同步監(jiān)視器的鎖的,而會在如下幾個情況下釋放鎖:
          ① 當(dāng)前線程的同步方法、代碼塊執(zhí)行結(jié)束的時候釋放
          ② 當(dāng)前線程在同步方法、同步代碼塊遇到break、return終止該代碼塊或方法的時候釋放
          ③ 出現(xiàn)未處理的error或exception導(dǎo)致異常結(jié)束的時候釋放
          ④ 程序執(zhí)行了同步對象wait方法,當(dāng)前線程暫停,釋放鎖

          那么,在上面的程序中,當(dāng)線程進入同步方法method1時獲得Service1的對象鎖,但是在執(zhí)行method1的時候調(diào)用了同步方法method2,按照正常情況,在執(zhí)行同步方法method2同樣需要獲得對象鎖,但是根據(jù)上面釋放鎖的條件,此時method1的對象鎖還沒有釋放,此時就會造成死鎖,無法繼續(xù)執(zhí)行method2。但是通過上面代碼的執(zhí)行結(jié)果來看,能夠正常執(zhí)行method2和method3,這就說明,在一個Synchronized修飾的方法或代碼塊的內(nèi)部調(diào)用本類的其他Synchronized修飾的方法或代碼塊時,是永遠可以得到鎖的。

          1.3 父子可繼承性

          可重入鎖支持在父子類繼承的環(huán)境中,示例代碼如下:

          public class Service2 {     public int i = 10;     public synchronized void mainMethod(){         i--;         System.out.println("main print i="+i);         try {             Thread.sleep(100);         } catch (InterruptedException e) {             e.printStackTrace();         }     } }
          public class Service3 extends Service2 {      public synchronized void subMethod(){         try{             while (i>0){                 i--;                 System.out.println("sub print i= "+i);                 Thread.sleep(100);                 this.mainMethod();             }         }catch (InterruptedException e){             e.printStackTrace();         }     } }
          public class MyThread extends Thread {      @Override     public void run(){         Service3 service3 = new Service3();         service3.subMethod();     }       public static void main(String[] args) {         MyThread myThread = new MyThread();         myThread.start();     } }

          運行結(jié)果如下:
          一起看看synchronized的4個特性
          此程序說明,當(dāng)存在父子類繼承關(guān)系時,子類完全可以通過“可重入鎖”調(diào)用父類的同步方法。

          2. 出現(xiàn)異常,鎖自動釋放

          當(dāng)一個線程執(zhí)行的代碼出現(xiàn)異常時,其所持有的鎖會自動釋放。
          驗證代碼如下:

          public class Service4 {      public synchronized void testMethod(){         if(Thread.currentThread().getName().equals("a")){             System.out.println("ThreadName= "+Thread.currentThread().getName()+" run beginTime="+System.currentTimeMillis());             int i=1;             while (i == 1){                 if((""+Math.random()).substring(0,8).equals("0.123456")){                     System.out.println("ThreadName= "+Thread.currentThread().getName()+" run exceptionTime="+System.currentTimeMillis());                   //Integer.parseInt("a");                 }             }         }else{             System.out.println("Thread B run time= "+System.currentTimeMillis());         }     } }
          public class ThreadA extends Thread{      private Service4 service4;      public ThreadA(Service4 service4){         this.service4 = service4;     }      @Override     public void run(){         service4.testMethod();     } }
          public class ThreadB extends Thread{      private Service4 service4;      public ThreadB(Service4 service4){         this.service4 = service4;     }      @Override     public void run(){         service4.testMethod();     } }
          public class Main {     public static void main(String[] args) {         try {             Service4 service4 = new Service4();              ThreadA a = new ThreadA(service4);             a.setName("a");             a.start();              Thread.sleep(500);              ThreadB b = new ThreadB(service4);             b.setName("b");             b.start();         } catch (InterruptedException e) {             e.printStackTrace();         }     } }

          注意Service4類中Integer.parseInt(“a”);此時處于被注釋狀態(tài),運行結(jié)果如下:
          一起看看synchronized的4個特性
          由于a線程沒有錯誤,while(true),此時a線程處于無限循環(huán)狀態(tài),鎖一直被a占用,b線程無法獲得鎖,即無法執(zhí)行b線程。

          將Service4類中Integer.parseInt(“a”);解開注釋,執(zhí)行的結(jié)果如下:

          一起看看synchronized的4個特性
            
          當(dāng)a線程發(fā)生錯誤時,b線程獲得鎖從而執(zhí)行,由此可見,當(dāng)方法出現(xiàn)異常時,鎖自動釋放。

          3. 將任意對象作為監(jiān)視器

          java支持對“任意對象”作為“對象監(jiān)視器”來實現(xiàn)同步的功能。這個“任意對象”大多數(shù)是實例變量及方法的參數(shù),使用格式為synchronized(非this對象x)同步代碼塊。
          示例代碼如下:

          public class StringLock {      private String lock = "lock";      public void method(){         synchronized (lock){             try {                 System.out.println("當(dāng)前線程: "+Thread.currentThread().getName() + "開始");                 Thread.sleep(1000);                 System.out.println("當(dāng)前線程: "+Thread.currentThread().getName() + "結(jié)束");             } catch (InterruptedException e) {                 e.printStackTrace();             }         }     }      public static void main(String[] args) {         final StringLock stringLock = new StringLock();         new Thread(new Runnable() {             @Override             public void run() {                 stringLock.method();             }         },"t1").start();          new Thread(new Runnable() {             @Override             public void run() {                 stringLock.method();             }         },"t2").start();     } }

          運行結(jié)果如下:
          一起看看synchronized的4個特性
          鎖非this對象具有一定的優(yōu)點:如果在一個類中有很多個synchronized方法,這時雖然能實現(xiàn)同步,但會受到阻塞,所以影響運行效率;但如果使用同步代碼塊鎖非this對象,則synchronized(非this)代碼塊中的程序與同步方法是異步的,不予其他鎖this同步方法爭搶this鎖,則可大大提高運行效率。

          4. 同步不具有繼承性

          父類的同步方法,在子類中重寫后不加同步關(guān)鍵字,是不會同步的,所以還得在子類的方法中添加synchronized關(guān)鍵字。

          推薦學(xué)習(xí):Java視頻教程

          贊(0)
          分享到: 更多 (0)
          網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號