zoukankan      html  css  js  c++  java
  • [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 + 原子变量 方式可以同时保证多线程环境下安全的变量读写。

  • 相关阅读:
    第40次全国计算机等级考试监考
    [再寄小读者之数学篇](2014-07-27 打印错误吧)
    日积月累的名典[2014-10-7]
    2014年全球“高被引科学家”数学类名单
    年轻尼姑的19句话
    PostgreSQL的 initdb 源代码分析之十六
    PostgreSQL的 initdb 源代码分析之十五
    PostgreSQL的 initdb 源代码分析之十四
    PostgreSQL的 initdb 源代码分析之十三
    PostgreSQL的 initdb 源代码分析之十二
  • 原文地址:https://www.cnblogs.com/driftingshine/p/4109995.html
Copyright © 2011-2022 走看看