volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性,即多线程环境中,使用 volatile 关键字的变量仅可以保证不同线程读取变量时,可以读到最新修改的变量值,但是修改变量值时,却不能保证线程安全(可能存在写值覆盖现象)。以下测试代码,展示了使用volatile关键字的几种方式。

 /**
* <b>volatile 关键字正确用法</b><br>
* @author Gaylen
* @version V1.1.0
* history
* 1.1.0, 2014年11月20日 Gaylen FE
* @since Java 6.0
*/
public class TestVolatile { /** volatile + atomic 保证读写安全 */
public static volatile AtomicInteger count1 = new AtomicInteger(0); /** volatile 实现读安全,但不能保证写安全 */
public static volatile int count2 = 0; /** volatile + synchronized 实现读写安全 */
public static volatile int count3 = 0; /** static 仅保证全局唯一,但不能保证读写安全 */
public static int count4 = 0; public static synchronized void count3Increment() {
TestVolatile.count3++;
} /** 测试线程数 */
public static final int numOfThread = 1000; /** 线程辅助类,保证所有线程执行完毕 */
private static CountDownLatch countDownLatch = new CountDownLatch(numOfThread); public static void increment() {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
count1.getAndIncrement();
count2++;
count3Increment();
count4++;
} /**
* 输出结果
* 等待所有线程执行完毕后,输出结果
*/
public static void print() {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("运行结果: count1=" + TestVolatile.count1.get());
System.out.println("运行结果: count2=" + TestVolatile.count2);
System.out.println("运行结果: count3=" + TestVolatile.count3);
System.out.println("运行结果: count4=" + TestVolatile.count4);
System.out.println("---------------------------------------"); } /**
* <b>程序入口</b><br>
* 同时启动1000个线程,进行增加操作
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < numOfThread; i++) {
new Thread(new Runnable() { @Override
public void run() {
for (int index = 0; index < 1000; index++) {
TestVolatile.increment();
}
countDownLatch.countDown();
}
}).start();
}
print();
}
}

测试程序输出结果如下:

运行结果: count1=1000000
运行结果: count2=998528
运行结果: count3=1000000
运行结果: count4=999892
---------------------------------------

通过测试程序可知,使用 volatile + synchronized 方式 或者 volatile + 原子变量 方式可以同时保证多线程环境下安全的变量读写。

[Java多线程] volatile 关键字正确使用方法的更多相关文章

  1. Java 多线程 - Volatile关键字

    作者: dreamcatcher-cx 出处: <http://www.cnblogs.com/chengxiao/> 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明 ...

  2. java多线程 -- volatile 关键字 内存 可见性

    内存可见性(Memory Visibility) 1 内存可见性(Memory Visibility)是指当某个线程正在使用对象状态而另一个线程在同时修改该状态,需要确保当一个线程修改了对象状态后,其 ...

  3. Java多线程——volatile关键字、发布和逸出

    1.volatile关键字 Java语言提供了一种稍弱的同步机制,即volatile变量.被volatile关键字修饰的变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在每次读取volatit ...

  4. Java多线程-----volatile关键字详解

       volatile原理     Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程.当把变量声明为volatile类型后, 编译器与运行时都会注意 ...

  5. JAVA多线程---volatile关键字

    加锁机制既可以确保可见性又可以保证原子性,而volatile变量只能确保可见性. 当把变量声明为volatile时候 编译器与运行时都会注意到这个变量是共享的,不会将该变量上的操作与其他内存操作一起重 ...

  6. 【转】java中volatile关键字的含义

    java中volatile关键字的含义   在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...

  7. 转:java中volatile关键字的含义

    转:java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...

  8. Java中Volatile关键字详解 (转自郑州的文武)

    java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 一.基本概念 先补充一下概念:J ...

  9. Java 多线程 —— synchronized关键字

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

随机推荐

  1. 通过XOML或者XAML的方式创建和启动工作流

    在Workflow Foundation中,提供了多种设计工作流的方式.例如 纯代码的方式(C#) 代码分离的方式(XOML+C#) 以上两种,可以从Visual Studio提供的项目模板中选择 他 ...

  2. Unity3d Inspector面板实现set/get访问器

    简单说一下属性和字段的区别:字段就是成员变量,而属性确实提供给外部访问内部成员变量的接口.之所以会有属性的出现,就是为了避免外部对类的成员的直接访问,通俗的说就是OOP中的封装思想. using Un ...

  3. IntelliJ IDEA 常用快捷键总结

    个人使用频率的高低排序: Alt+enter               代码提示 Alt+7                查看类的方法 Alt+insert        生成get和set方法 ...

  4. Java中泛型T和Class<T>以及Class<?>的理解(转)

    注意:class是java的关键字, 在声明Java类时使用; Class类的实例表示Java应用运行时的类(class ans enum)或接口(interface and annotation)( ...

  5. erlang debugger

    http://erlang.org/doc/apps/debugger/debugger_chapter.html

  6. exec: "docker-proxy": executable file not found in $PATH

    在执行 docker run 操作的时候,一直报如下错误: [root@etcd1 vagrant]# docker run --name redis-6379 -p 6379:6379 -d --r ...

  7. Go -- etcd详解(转)

    CoreOS是一个基于Docker的轻量级容器化Linux发行版,专为大型数据中心而设计,旨在通过轻量的系统架构和灵活的应用程序部署能力简化数据中心的维护成本和复杂度.CoreOS作为Docker生态 ...

  8. Docker实战(一):基础命令

    # 在ubuntu中安装docker $ sudo apt-get install docker.io # 查看docker的版本信息 $ docker version # 查看安装docker的信息 ...

  9. .Net ToString Format [转]

    源文 :http://blog.csdn.net/luyifeiniu/article/category/25663/2 stringstr1 =string.Format("{0:N1}& ...

  10. Redis绑定多个ip地址

    Redis绑定多个ip地址 学习了:https://www.zhihu.com/question/20346112/answer/17157379 注意,用空格进行分隔 bind 127.0.0.1 ...