lazy initialization 實現 Singleton 時 synchronized 的必要性說明

          首先了解一下Singleton模式通常的兩種表現形式:
          第一種形式:
          public class Singleton { 
              
          private Singleton(){} 
              
          //在自己內部定義自己一個實例,是不是很奇怪? 
              
          //注意這是private 只供內部調用 
              private static Singleton instance = new Singleton(); 
              
          //這里提供了一個供外部訪問本class的靜態方法,可以直接訪問 
              public static Singleton getInstance() { 
                 
          return instance; 
              }
          }
          第二種形式:
          public class Singleton { 
             private static Singleton instance = null
             public static synchronized Singleton getInstance() { 
                //這個方法比上面有所改進,不用每次都進行生成對象,只是第一次 
                //使用時生成實例,提高了效率! 
                if (instance==null) instance=new Singleton(); 
                return instance; 
             } 
          }
             
          使用Singleton.getInstance()可以訪問單態類。 
             上面第二中形式就是lazy initialization,也就是說第一次調用時初始Singleton,以后就不用再生成了。 
             注意到lazy initialization形式中的synchronized,這個synchronized很重要,如果沒有synchronized,那么使用getInstance()是有可能得到多個Singleton實例。

             那么為什么只有使用synchronized關鍵字才可以達到單態的目的呢?synchronized到底有什么含義呢?
             synchronized 關鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。
          1. synchronized 方法:通過在方法聲明中加入 synchronized關鍵字來聲明 synchronized 方法。如:
          public synchronized void accessVal(int newVal); 
             synchronized 方法控制對類成員變量的訪問:每個類實例對應一把鎖,每個 synchronized 方法都必須獲得調用該方法的類實例的鎖方能執行,否則所屬線程阻塞,方法一旦執行,就獨占該鎖,直到從該方法返回時才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進入可執行狀態。這種機制確保了同一時刻對于每一個類實例,其所有聲明為 synchronized 的成員函數中至多只有一個處于可執行狀態(因為至多只有一個能夠獲得該類實例對應的鎖),從而有效避免了類成員變量的訪問沖突(只要所有可能訪問類成員變量的方法均被聲明為 synchronized)。 
             在 Java 中,不光是類實例,每一個類也對應一把鎖,這樣我們也可將類的靜態成員函數聲明為 synchronized ,以控制其對類的靜態成員變量的訪問。 
             synchronized 方法的缺陷:若將一個大的方法聲明為synchronized 將會大大影響效率,典型地,若將線程類的方法 run() 聲明為 synchronized ,由于在線程的整個生命期內它一直在運行,因此將導致它對本類任何 synchronized 方法的調用都永遠不會成功。當然我們可以通過將訪問類成員變量的代碼放到專門的方法中,將其聲明為 synchronized ,并在主方法中調用來解決這一問題,但是 Java 為我們提供了更好的解決辦法,那就是 synchronized 塊。
          2. synchronized 塊:通過 synchronized關鍵字來聲明synchronized 塊。語法如下:
          synchronized(syncObject) { 
             //允許訪問控制的代碼 
          synchronized 塊是這樣一個代碼塊,其中的代碼必須獲得對象 syncObject (如前所述,可以是類實例或類)的鎖方能執行,具體機制同前所述。由于可以針對任意代碼塊,且可任意指定上鎖的對象,故靈活性較高。


          對synchronized(this)的一些理解

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

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

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

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

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

          posted on 2007-07-25 14:14 萬博 閱讀(475) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          <2007年7月>
          24252627282930
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234

          導航

          統計

          留言簿(1)

          隨筆檔案(13)

          搜索

          積分與排名

          最新隨筆

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 乡宁县| 万载县| 水城县| 正阳县| 尚志市| 康马县| 张家口市| 青岛市| 黄山市| 五莲县| 马鞍山市| 枞阳县| 白山市| 中西区| 麦盖提县| 基隆市| 荔浦县| 博爱县| 长子县| 玉林市| 额尔古纳市| 鹿邑县| 玉屏| 阿坝县| 津南区| 沁阳市| 鲁甸县| 高邑县| 天台县| 新河县| 宁陵县| 平远县| 吴忠市| 股票| 巴林左旗| 苍山县| 磴口县| 涞水县| 石嘴山市| 凤冈县| 唐河县|