Synchronized含義

Synchronized 鎖定的是對象而非函數或代碼。

每個Object都有一把鎖(Lock),當進行到Synchronized語句或函數的時候,這把鎖就會被當前的線程(thread)拿走,其他的(thread)再去訪問的時候拿不到鎖就被暫停了。

只有當Synchronized的是同一個對象的纔是線程安全的(thread-safe)

class Test{

      public Synchronized void method1(){               //鎖住的對象是this 即當前對象

          //........              

      }

        public void method2(){                                  // 鎖住的對象是this  所以和method1是等同的,

                                                                                 //他們之間也是線程安全的。         

           Synchronized(this){                                     

                   //................

            }

     }

     public Synchronized static void method3(){      //鎖住的對象是Test.class,注:

                                                                                       //Test.class 在虛擬機中只可能有一個,但是Test長生的對象 

                                                                                     //可以有多個,因爲method3和method1,method2鎖住的

                                                                                    //不同,所以他們之間不同步,不是線程安全的。

    }

    public void method4(){                                     //跟method3是相同的效果。

         Synchronized(Test.class){

              //............

          }

    }

}

這是Synchronized static 函數與Synchronized instance函數之間的區別。

-----------------------------------------

class Test implements Runnable{

    private int[] intArray = new int[10]

    public synchronized void addToArray(int[] ar){

  // modify the intArray 

  }

  public synchronized void subArray(int[] ary){

    // modify the intArray

}

  public int[] getIntArray(){
 

  return intArray;

  }

}

很多人看到上面這個例子馬上可以斷定這個Test一定是同步的。其實不然,因爲他暴露了intArray給外界,所以可以不通過上面兩個方法去修改intArray這個filed,假如intArray是public protected數據那就更不行了。那我要訪問這個intArray怎麼辦,那就只好clone一個intArray了。

  public int[] getIntArray(){
 

  return intArray.clone();

  }

-------------------------------------------

private byte[] lock  =  new byte[0];//建議用使用這樣的lock,因爲這個不任何對象都經濟。

創建一個元素個數爲0的array,並不象創建對象那樣需要調用構造函數,所以速度會快些,此外,內含元素的byte arrays往往在jvm中有着比int arrays 更緊湊的表述形式。

---------------------------------------------

long clocktime = 123123.1;

很多人看到上面這個操作的時候肯定會以爲這個一定是安全的,因爲會認爲這是個原子操作。呵呵 錯了!

long 數據一般採用64bit(跨越兩個32bit word)表述。或許某些jvm實現產品將64-bit操作視爲不可分割的(atomic),但現今大部分jvm實現產品都不這樣。而是將它視爲兩個獨立的32-bit操作。所以有可能發生舊值的前32bit以及其新值的後32bit組成。這個返回值是錯誤的。這是因爲,面對64bit數據,jvm必須執行一次以上的讀寫動作。先前討論的“私有專用副本”與“主內存”也是這個問題。想要改正這個問題,有兩個選擇:同步控制對clocktime變量的訪問,或是將它聲明爲volatile。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章