<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      安卓筆記俠

      專注安卓開發

      導航

      Java并發編程(四)synchronized

      一.synchronized同步方法或者同步塊

      在了解synchronized關鍵字的使用方法之前,我們先來看一個概念:互斥鎖,顧名思義:能到達到互斥訪問目的的鎖。

      舉個簡單的例子:如果對臨界資源加上互斥鎖,當一個線程在訪問該臨界資源時,其他線程便只能等待。

      在Java中,每一個對象都擁有一個鎖標記(monitor),也稱為監視器,多線程同時訪問某個對象時,線程只有獲取了該對象的鎖才能訪問。

      在Java中,可以使用synchronized關鍵字來標記一個方法或者代碼塊,當某個線程調用該對象的synchronized方法或者訪問synchronized代碼塊時,這個線程便獲得了該對象的鎖,其他線程暫時無法訪問這個方法,只有等待這個方法執行完畢或者代碼塊執行完畢,這個線程才會釋放該對象的鎖,其他線程才能執行這個方法或者代碼塊。

      下面通過幾個簡單的例子來說明synchronized關鍵字的使用:

      1.synchronized方法

      下面這段代碼中兩個線程分別調用insertData對象插入數據:

      public class Test {
       
          public static void main(String[] args)  {
              final InsertData insertData = new InsertData();
               
              new Thread() {
                  public void run() {
                      insertData.insert(Thread.currentThread());
                  };
              }.start();
               
               
              new Thread() {
                  public void run() {
                      insertData.insert(Thread.currentThread());
                  };
              }.start();
          }  
      }
       
      class InsertData {
          private ArrayList<Integer> arrayList = new ArrayList<Integer>();
           
          public synchronized  void insert(Thread thread){
              for(int i=0;i<5;i++){
                  System.out.println(thread.getName()+"在插入數據"+i);
                  arrayList.add(i);
              }
          }
      }
      View Code

      從上輸出結果說明,Thread-1插入數據是等Thread-0插入完數據之后才進行的。說明Thread-0和Thread-1是順序執行insert方法的。

      這就是synchronized方法。

      不過有幾點需要注意:

      1)當一個線程正在訪問一個對象的synchronized方法,那么其他線程不能訪問該對象的其他synchronized方法。這個原因很簡單,因為一個對象只有一把鎖,當一個線程獲取了該對象的鎖之后,其他線程無法獲取該對象的鎖,所以無法訪問該對象的其他synchronized方法。

      2)當一個線程正在訪問一個對象的synchronized方法,那么其他線程能訪問該對象的非synchronized方法。這個原因很簡單,訪問非synchronized方法不需要獲得該對象的鎖,假如一個方法沒用synchronized關鍵字修飾,說明它不會使用到臨界資源,那么其他線程是可以訪問這個方法的,

      3)如果一個線程A需要訪問對象object1的synchronized方法fun1,另外一個線程B需要訪問對象object2的synchronized方法fun1,即使object1和object2是同一類型,也不會產生線程安全問題,因為他們訪問的是不同的對象,所以不存在互斥問題。

      2.synchronized代碼塊

      當在某個線程中執行這段代碼塊,該線程會獲取對象synObject的鎖,從而使得其他線程無法同時訪問該代碼塊。

      synObject可以是this,代表獲取當前對象的鎖,也可以是類中的一個屬性,代表獲取該屬性的鎖。

      比如上面的insert方法可以改成以下兩種形式:
      
      class InsertData {
          private ArrayList<Integer> arrayList = new ArrayList<Integer>();
           
          public void insert(Thread thread){
              synchronized (this) {
                  for(int i=0;i<100;i++){
                      System.out.println(thread.getName()+"在插入數據"+i);
                      arrayList.add(i);
                  }
              }
          }
      }
      
      class InsertData {
          private ArrayList<Integer> arrayList = new ArrayList<Integer>();
          private Object object = new Object();
           
          public void insert(Thread thread){
              synchronized (object) {
                  for(int i=0;i<100;i++){
                      System.out.println(thread.getName()+"在插入數據"+i);
                      arrayList.add(i);
                  }
              }
          }
      }
      
      從上面可以看出,synchronized代碼塊使用起來比synchronized方法要靈活得多。因為也許一個方法中只有一部分代碼只需要同步,如果此時對整個方法用synchronized進行同步,會影響程序執行效率。而使用synchronized代碼塊就可以避免這個問題,synchronized代碼塊可以實現只對需要同步的地方進行同步
      View Code

       

      另外,每個類也會有一個鎖,它可以用來控制對static數據成員的并發訪問。

      并且如果一個線程執行一個對象的非static synchronized方法,另外一個線程需要執行這個對象所屬類的static synchronized方法,此時不會發生互斥現象,因為訪問static synchronized方法占用的是類鎖,而訪問非static synchronized方法占用的是對象鎖,所以不存在互斥現象。(對象級別的synchronized,還有類級別的synchronized.鎖定的是整 個clz.class)

      看下面這段代碼就明白了:
      
      public class Test {
       
          public static void main(String[] args)  {
              final InsertData insertData = new InsertData();
              new Thread(){
                  @Override
                  public void run() {
                      insertData.insert();
                  }
              }.start(); 
              new Thread(){
                  @Override
                  public void run() {
                      insertData.insert1();
                  }
              }.start();
          }  
      }
       
      class InsertData { 
          public synchronized void insert(){
              System.out.println("執行insert");
              try {
                  Thread.sleep(5000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              System.out.println("執行insert完畢");
          }
           
          public synchronized static void insert1() {
              System.out.println("執行insert1");
              System.out.println("執行insert1完畢");
          }
      }
      View Code

      執行結果;

      第一個線程里面執行的是insert方法,不會導致第二個線程執行insert1方法發生阻塞現象。

       

      下面我們看一下synchronized關鍵字到底做了什么事情,我們來反編譯它的字節碼看一下,下面這段代碼反編譯后的字節碼為:

      public class InsertData {
          private Object object = new Object();
           
          public void insert(Thread thread){
              synchronized (object) {
               
              }
          }
           
          public synchronized void insert1(Thread thread){
               
          }
           
          public void insert2(Thread thread){
               
          }
      }
      View Code

        從反編譯獲得的字節碼可以看出,synchronized代碼塊實際上多了monitorenter和monitorexit兩條指令。monitorenter指令執行時會讓對象的鎖計數加1,而monitorexit指令執行時會讓對象的鎖計數減1,其實這個與操作系統里面的PV操作很像,操作系統里面的PV操作就是用來控制多個線程對臨界資源的訪問。對于synchronized方法,執行中的線程識別該方法的 method_info 結構是否有 ACC_SYNCHRONIZED 標記設置,然后它自動獲取對象的鎖,調用方法,最后釋放鎖。如果有異常發生,線程自動釋放鎖。

        

        有一點要注意:對于synchronized方法或者synchronized代碼塊,當出現異常時,JVM會自動釋放當前線程占用的鎖,因此不會由于異常導致出現死鎖現象

       

      二.java單例模式(雙重檢查加鎖)的原因

      雙重檢查加鎖,只有在第一次實例化時,才啟用同步機制,提高了性能。

      public class Singleton{ 
         private static Singleton instance = null;//是否是final的不重要,因為最多只可能實例化一次。 
         private Singleton(){} 
         public static Singleton getInstance(){ 
             if(instance == null){ 
                 //雙重檢查加鎖,只有在第一次實例化時,才啟用同步機制,提高了性能。 
                 synchronized(Singleton.Class){ 
                     if(instance == null){ 
                         instance = new Singleton(); 
                     } 
                 } 
             } 
             return instance; 
      } 

       

      posted on 2016-12-04 22:03  安卓筆記俠  閱讀(366)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 日本精品一区二区不卡| 人妻系列中文字幕精品| 亚洲av激情一区二区三区| 久青草久青草视频在线观看| 亚洲熟妇自偷自拍另欧美| 高清日韩一区二区三区视频| 特级做a爰片毛片免费看无码 | 久久久无码精品亚洲日韩蜜臀浪潮| 亚洲精品国产精品不乱码| 国产久免费热视频在线观看| FC2免费人成在线视频| 久热爱精品视频线路一| 国产精品日日摸夜夜添夜夜添无码| 美女午夜福利视频一区二区| 亚洲男人AV天堂午夜在| 人妻系列无码专区免费| 久久超碰色中文字幕超清| 长岛县| 日本亚洲一区二区精品久久| 国产成人欧美日韩在线电影| 99亚洲男女激情在线观看| 亚洲午夜激情久久加勒比| 人妻中文字幕精品一页| 最近中文字幕国产精选| 亚洲国产精品特色大片观看完整版 | 亚洲精品乱码久久久久久自慰| 久久精品国内一区二区三区| 固原市| 色综合AV综合无码综合网站| 极品少妇的粉嫩小泬看片| 亚洲老女人区一区二视频| 国产自产av一区二区三区性色| 国产中文字幕一区二区| 2020年最新国产精品正在播放| 美女裸体黄网站18禁止免费下载| 日本欧美大码a在线观看| 老熟女重囗味hdxx69| 亚洲乱码中文字幕小综合| 婷婷丁香五月深爱憿情网| 黑人大战中国av女叫惨了| 九九热视频精品在线播放|