JAVA中的同步處理

來源:互聯網
上載者:User
這裡的同步只對單個Java應用程式來說,至於資料庫同步,檔案同步等就不是這裡討論的問題了。 同步和多線程的關係
1.沒有多線程環境就不需要同步。
2.即使有多線程環境也不一定需要同步。 為什麼要同步:
為了防止多個線程對同一資料的修改,所以需要同步,否則會造成資料不一致。
Java提供了非常方便的多線程支援,所以說同步問題比較普遍,尤其是Servlet和
JSP的安全執行緒問題特別明顯。
http://blog.csdn.net/treeroot/archive/2004/09/03/93881.aspx 同步的實質:
Java同步其實就是獲得對象的同步鎖,其他線程就只能等待。我們的大部分程式都不是安全執行緒的,因為沒有進行同步,而且我們沒有必要,因為大部分情況根本沒有多線程環境。

只舉一個例子說明同步的實質。

代碼1:
class SynTest{
    synchronized static method(){
 //這個方法是同步的方法,每次只有一個線程可以進來
        System.out.println("begin");
        try{Thread.sleep(2000);}
        System.out.println("end"); 
    }
    public static void main(String[] args){
       //啟動10個線程,這裡用了匿名類,因為確實方便不少。
       for(int i=0;i<10;i++){
            new Thread(){
                public void run(){
                    method();
                }
            }.start();
        }
    }
}
很容易看到每個線程必須等待前一個線程退出方法method後才可以進去。
上面的同步方法可以有另外的兩種等價方式: 代碼2:
class SynTest{
    static method(){
        synchronized(SynTest.class){
          //這個方法雖然不是同步的方法,但是每次只有一個線程可以進到同步塊
          System.out.println("begin");
          try{Thread.sleep(2000);}
          System.out.println("end");
        } 
    }
    public static void main(String[] args){
       //啟動10個線程,這裡用了匿名類,因為確實方便不少。
       for(int i=0;i<10;i++){
            new Thread(){
                public void run(){
                    method();
                }
            }.start();
       }
    }
} 代碼3:
class SynTest{
    private static Object lock=new Object();
    static method(){
           synchronized(lock){
          //這個方法用一個專門的對象作為鎖。
          System.out.println("begin");
          try{Thread.sleep(2000);}
          System.out.println("end");
        } 
    }
    public static void main(String[] args){
       //啟動10個線程,這裡用了匿名類,因為確實方便不少。
       for(int i=0;i<10;i++){
            new Thread(){
                public void run(){
                    method();
                }
            }.start();
       }
    }
} 其實上面三種情況基本上是等價的,不過第三種方式很常見,估計會有效能上的提高吧,畢竟鎖定一個小對象看起來比鎖定一個大對象容易一點。 上面的是靜態方法,如果是非靜態話,代碼2的表現為 synchronized(this)。
這裡先說明一點,同步和是否安全執行緒和方法是否是靜態一點關係都沒有。 如果判斷一個類或者一個方法是否安全執行緒的呢?
假設一個類沒有提供直接修改成員變數的操作,也就是算只能通過方法修改
對象。我們很容易得出結論,只有所有的方法是安全執行緒的,這個類才是線程
安全的。那麼如何判斷一個方法是否安全執行緒的,只有看說明文檔或者閱讀源碼了,不過可以肯定的說大部分都不是安全執行緒的,從方法聲明是看不出來的。
class Math{
     public static int safePow(int x,int y){//假設y大於0
        int res=x;
        for(int i=1;i<y;i++) res*=x;
        return res;
     }
     public static int unsafePow(int x,int y){
        pow=y;
        return pow(x);
     }
     private static int pow;
     private static int pow(int x){
        int res=x;
        for(int i=1;i<pow;i++) res*=x;
        return res;
     }
}
我都不知道怎麼回舉這麼無聊的例子,而且我發現這個問題腦子裡很清楚,卻很難表達清楚,看一下兩個線程調用unsafePow的例子。
Thread1: unsafePow(3,3);
Thread2:     unsafePow(2,2);
假設Thread1執行到 pow=y;進入方法pow(int x);
此時pow=3;
然後Thread2執行pow=y; 進入方法pow(int x);
此時pow=2;
然後線程1執行pow(int x)方法應該等到的是3的2次方,導致錯誤,所以說
這個方法不是安全執行緒的。 安全執行緒的關鍵就是對成員變數的修改(類變數或者執行個體變數,兩者在這裡都是
一樣的),而且對於存取方法同樣存線上程安全問題。
我們知道Hashtable是安全執行緒的,因為所有的方法都同步了,也就是說最多隻能同時有一個線程對Hashtable操作,那麼我們認為它是安全執行緒的。那麼假設它的size()方法不同步,
那就有可能你調用size方法還沒有返回,一個線程又添加了一個資料,這個時候你讀取到的值應該是正確的值,但是這個size方法還沒有返回,又一個線程刪除了一個資料,這個時候你返回的就是一個錯誤的大小了。 Hashtable也需要同步,當然Hashtable是安全執行緒的,Java文檔也有說明,但是不等於安全執行緒就不要同步壓。
public class SynHashtable{ 
public static void main(String[] args)
 {
  final Hashtable ht=new Hashtable();
  ht.put(new Object(),"Quick to Death");
  
  new Thread(){
   public void run(){
    while(true){
     if(ht.size()<10){
      ht.put(new  Object(),"object");
     }
     else{
      ht.clear();
     }
    }
   }
  }.start();
  
  new Thread(){
   public void run(){
    unsafe(ht);
   }
  }.start();
   
  
 }  static void unsafe(Hashtable ht){
  while(true){
  //synchronized(ht){
  Iterator it=ht.values().iterator();
  while(it.hasNext())
   System.out.println(it.next());
  }
  //}
 }
}
如果不同步的話很快就會崩潰。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.