volatile關鍵字相信瞭解Java多線程的讀者都很清楚它的做用。volatile關鍵字用於聲明簡單類型變量,如int、float、 boolean等數據類型。若是這些簡單數據類型聲明爲volatile,對它們的操做就會變成原子級別的。但這有必定的限制。例如,下面的例子中的n就 不是原子級別的:
Java代碼
- package mythread;
-
- public class JoinThread extends Thread
- {
- public static volatile int n = 0 ;
- public void run()
- {
- for ( int i = 0 ; i < 10 ; i ++ )
- try
- {
- n = n + 1 ;
- sleep( 3 ); // 爲了使運行結果更隨機,延遲3毫秒
-
- }
- catch (Exception e)
- {
- }
- }
-
- public static void main(String[] args) throws Exception
- {
-
- Thread threads[] = new Thread[ 100 ];
- for ( int i = 0 ; i < threads.length; i ++ )
- // 創建100個線程
- threads[i] = new JoinThread();
- for ( int i = 0 ; i < threads.length; i ++ )
- // 運行剛纔創建的100個線程
- threads[i].start();
- for ( int i = 0 ; i < threads.length; i ++ )
- // 100個線程都執行完後繼續
- threads[i].join();
- System.out.println( " n= " + JoinThread.n);
- }
- }
若是對n的操做是原子級別的,最後輸出的結果應該爲n=1000,而在執行上面積代碼時,不少時侯輸出的n都小於1000,這說明n=n+1不是原子級別 的操做。緣由是聲明爲volatile的簡單變量若是當前值由該變量之前的值相關,那麼volatile關鍵字不起做用,也就是說以下的表達式都不是原子 操做:
n = n + 1 ;
n ++ ;
若是要想使這種狀況變成原子操做,須要使用synchronized關鍵字,如上的代碼能夠改爲以下的形式:
Java代碼
- package mythread;
-
- public class JoinThread extends Thread
- {
- public static int n = 0 ;
-
- public static synchronized void inc()
- {
- n ++ ;
- }
- public void run()
- {
- for ( int i = 0 ; i < 10 ; i ++ )
- try
- {
- inc(); // n = n + 1 改爲了 inc();
- sleep( 3 ); // 爲了使運行結果更隨機,延遲3毫秒
-
- }
- catch (Exception e)
- {
- }
- }
-
- public static void main(String[] args) throws Exception
- {
-
- Thread threads[] = new Thread[ 100 ];
- for ( int i = 0 ; i < threads.length; i ++ )
- // 創建100個線程
- threads[i] = new JoinThread();
- for ( int i = 0 ; i < threads.length; i ++ )
- // 運行剛纔創建的100個線程
- threads[i].start();
- for ( int i = 0 ; i < threads.length; i ++ )
- // 100個線程都執行完後繼續
- threads[i].join();
- System.out.println( " n= " + JoinThread.n);
- }
- }
上面的代碼將n=n+1改爲了inc(),其中inc方法使用了synchronized關鍵字進行方法同步。所以,在使用volatile關鍵字時要慎 重,並非只要簡單類型變量使用volatile修飾,對這個變量的全部操做都是原來操做,當變量的值由自身的上一個決定時,如n=n+一、n++ 等,volatile關鍵字將失效,只有當變量的值和自身上一個值無關時對該變量的操做纔是原子級別的,如n = m + 1,這個就是原級別的。因此在使用volatile關鍵時必定要謹慎,若是本身沒有把握,可使用synchronized來代替volatile。