熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

Java多線程初學者指南(12):使用Synchronized塊同步變量

2013-11-23 19:45:09  來源: Java高級技術 

  我們可以通過synchronized塊來同步特定的靜態或非靜態方法要想實現這種需求必須為這些特性的方法定義一個類變量然後將這些方法的代碼用synchronized塊括起來並將這個類變量作為參數傳入synchronized塊下面的代碼演示了如何同步特定的類方法

       package mythread;
    
    public class SyncThread extends Thread
    {
        private static String sync = ;
        private String methodType = ;
    
        private static void method(String s)
        {
            synchronized (sync)
            {
                sync = s;
                Systemoutprintln(s);
                while (true);
            }
        }
        public void method()
        {
            method(method);
        }
        public static void staticMethod()
        {
            method(staticMethod);
        }
        public void run()
        {
            if (methodTypeequals(static))
                staticMethod();
            else if (methodTypeequals(nonstatic))
                method();
        }
        public SyncThread(String methodType)
        {
            thodType = methodType;
        }
        public static void main(String[] args) throws Exception
        {
            SyncThread sample = new SyncThread(nonstatic);
            SyncThread sample = new SyncThread(static);
            samplestart();
            samplestart();
        }
    }

  運行結果如下

   method
staticMethod

  看到上面的運行結果很多讀者可能感到驚奇在上面的代碼中method和staticMethod方法使用了靜態字符串變量sync進行同步這兩個方法只能有一個同時執行而這兩個方法都會執行行的無限循環語句因此輸出結果只能是method和staticMethod其中之一但這個程序將這兩個字符串都輸出了

  出現這種結果的願意很簡單我們看一下行就知道了原來在這一行將sync的值改變了在這裡要說一下Java中的String類型String類型和Java中其他的復雜類型不同在使用String型變量時只要給這個變量賦一次值Java就會創建個新的String類型的實例如下面的代碼所示

   String s = hello;
Systemoutprintln(shashCode());
s = world;
Systemoutprintln(shashCode()); 

  在上面的代碼中第一個s和再次賦值後的s的hashCode的值是不一樣的由於創建String類的實例並不需要使用new因此在同步String類型的變量時要注意不要給這個變量賦值否則會使變量無法同步

  由於在行已經為sync創建了一個新的實例假設method先執行當method方法執行了行的代碼後sync的值就已經不是最初那個值了而method方法鎖定的仍然是sync變量最初的那個值而在這時staticMethod正好執行到synchronized(sync)在staticMethod方法中要鎖定的這個sync和method方法鎖定的sync已經不是一個了因此這兩個方法的同步性已經被破壞了

  解決以上問題的方法當然是將行去掉在本例中加上這行只是為了說明使用類變量來同步方法時如果在synchronized塊中將同步變量的值改變就會破壞方法之間的同步為了徹底避免這種情況發生在定義同步變量時可以使用final關鍵字如將上面的程序中的行可改成如下形式

   private final static String sync = ;

  使用final關鍵字後sync只能在定義時為其賦值並且以後不能再修改如果在程序的其他地方給sync賦了值程序就無法編譯通過在Eclipse等開發工具中會直接在錯誤的地方給出提示

  我們可以從兩個角度來理解synchronized塊如果從類方法的角度來理解可以通過類變量來同步相應的方法如果從類變量的角度來理解可以使用synchronized塊來保證某個類變量同時只能被一個方法訪問不管從哪個角度來理解它們的實質都是一樣的就是利用類變量來獲得同步鎖通過同步鎖的互斥性來實現同步

  注意在使用synchronized塊時應注意synchronized塊只能使用對象作為它的參數如果是簡單類型的變量(如intcharboolean等)不能使用synchronized來同步


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27400.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.