volatile變量具有synchronized的可見性特性,但是不具備原子特性,即多線程環境中,使用 volatile 關鍵字的變量僅可以保證不同線程讀取變量時,可以讀到最新修改的變量值,但是修改變量值時,卻不能保證線程安全(可能存在寫值覆蓋現象)。以下測試代碼,展示了使用volatile關鍵字的幾種方式。
1 /** 2 * <b>volatile 關鍵字正確用法</b><br> 3 * @author Gaylen 4 * @version V1.1.0 5 * history 6 * 1.1.0, 2014年11月20日 Gaylen FE 7 * @since Java 6.0 8 */ 9 public class TestVolatile {10 11 /** volatile + atomic 保證讀寫安全 */12 public static volatile AtomicInteger count1 = new AtomicInteger(0);13 14 /** volatile 實現讀安全,但不能保證寫安全 */15 public static volatile int count2 = 0;16 17 /** volatile + synchronized 實現讀寫安全 */18 public static volatile int count3 = 0;19 20 /** static 僅保證全局唯一,但不能保證讀寫安全 */21 public static int count4 = 0;22 23 public static synchronized void count3Increment() {24 TestVolatile.count3++;25 }26 27 /** 測試線程數 */28 public static final int numOfThread = 1000;29 30 /** 線程輔助類,保證所有線程執行完畢 */31 PRivate static CountDownLatch countDownLatch = new CountDownLatch(numOfThread);32 33 public static void increment() {34 try {35 Thread.sleep(1);36 } catch (InterruptedException e) {37 }38 count1.getAndIncrement();39 count2++;40 count3Increment();41 count4++;42 }43 44 /**45 * 輸出結果46 * 等待所有線程執行完畢后,輸出結果47 */48 public static void print() {49 try {50 countDownLatch.await();51 } catch (InterruptedException e) {52 e.printStackTrace();53 }54 System.out.println("運行結果: count1=" + TestVolatile.count1.get());55 System.out.println("運行結果: count2=" + TestVolatile.count2);56 System.out.println("運行結果: count3=" + TestVolatile.count3);57 System.out.println("運行結果: count4=" + TestVolatile.count4);58 System.out.println("---------------------------------------");59 60 }61 62 /**63 * <b>程序入口</b><br>64 * 同時啟動1000個線程,進行增加操作65 * @param args66 */67 public static void main(String[] args) {68 for (int i = 0; i < numOfThread; i++) {69 new Thread(new Runnable() {70 71 @Override72 public void run() {73 for (int index = 0; index < 1000; index++) {74 TestVolatile.increment();75 }76 countDownLatch.countDown();77 }78 }).start();79 }80 print();81 }82 }測試程序輸出結果如下:
運行結果: count1=1000000運行結果: count2=998528運行結果: count3=1000000運行結果: count4=999892---------------------------------------
通過測試程序可知,使用 volatile + synchronized 方式 或者 volatile + 原子變量 方式可以同時保證多線程環境下安全的變量讀寫。
新聞熱點
疑難解答