[Java多线程] volatile 关键字正确使用方法

    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 args
66      */
67     public static void main(String[] args) {
68         for (int i = 0; i < numOfThread; i++) {
69             new Thread(new Runnable() {
70 
71                 @Override
72                 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 + 原子变量 方式可以同时保证多线程环境下安全的变量读写。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。