文章目录

  • 什么时候使用volatile
  • Happens-Before

java中的Volatile关键字使用

在本文中,我们会介绍java中的一个关键字volatile。 volatile的中文意思是易挥发的,不稳定的。那么在java中使用是什么意思呢?

我们知道,在java中,每个线程都会有个自己的内存空间,我们称之为working memory。这个空间会缓存一些变量的信息,从而提升程序的性能。当执行完某个操作之后,thread会将更新后的变量更新到主缓存中,以供其他线程读写。

因为变量存在working memory和main memory两个地方,那么就有可能出现不一致的情况。 那么我们就可以使用Volatile关键字来强制将变量直接写到main memory,从而保证了不同线程读写到的是同一个变量。

什么时候使用volatile

那么我们什么时候使用volatile呢?当一个线程需要立刻读取到另外一个线程修改的变量值的时候,我们就可以使用volatile。我们来举个例子:

public class VolatileWithoutUsage {private  int count = 0;public void incrementCount() {count++;}public int getCount() {return count;}
}

这个类定义了一个incrementCount()方法,会去更新count值,我们接下来在多线程环境中去测试这个方法:

    @Testpublic void testWithoutVolatile() throws InterruptedException {ExecutorService service= Executors.newFixedThreadPool(3);VolatileWithoutUsage volatileWithoutUsage=new VolatileWithoutUsage();IntStream.range(0,1000).forEach(count ->service.submit(volatileWithoutUsage::incrementCount) );service.shutdown();service.awaitTermination(1000, TimeUnit.MILLISECONDS);assertEquals(1000,volatileWithoutUsage.getCount() );}

运行一下,我们会发现结果是不等于1000的。


java.lang.AssertionError:
Expected :1000
Actual   :999

这是因为多线程去更新同一个变量,我们在上篇文章也提到了,这种情况可以通过加Synchronized关键字来解决。

那么是不是我们加上Volatile关键字后就可以解决这个问题了呢?

public class VolatileFalseUsage {private volatile int count = 0;public void incrementCount() {count++;}public int getCount() {return count;}}

上面的类中,我们加上了关键字Volatile,我们再测试一下:

    @Testpublic void testWithVolatileFalseUsage() throws InterruptedException {ExecutorService service= Executors.newFixedThreadPool(3);VolatileFalseUsage volatileFalseUsage=new VolatileFalseUsage();IntStream.range(0,1000).forEach(count ->service.submit(volatileFalseUsage::incrementCount) );service.shutdown();service.awaitTermination(5000, TimeUnit.MILLISECONDS);assertEquals(1000,volatileFalseUsage.getCount() );}

运行一下,我们会发现结果还是错误的:

java.lang.AssertionError:
Expected :1000
Actual   :992
~~为什么呢? 我们先来看下count++的操作,count++可以分解为三步操作,1. 读取count的值,2.给count加1, 3.将count写回内存。添加Volatile关键词只能够保证count的变化立马可见,而不能保证1,2,3这三个步骤的总体原子性。 要实现总体的原子性还是需要用到类似Synchronized的关键字。下面看下正确的用法:~~~java
public class VolatileTrueUsage {private volatile int count = 0;public void setCount(int number) {count=number;}public int getCount() {return count;}
}
    @Testpublic void testWithVolatileTrueUsage() throws InterruptedException {VolatileTrueUsage volatileTrueUsage=new VolatileTrueUsage();Thread threadA = new Thread(()->volatileTrueUsage.setCount(10));threadA.start();Thread.sleep(100);Thread reader = new Thread(() -> {int valueReadByThread = volatileTrueUsage.getCount();assertEquals(10, valueReadByThread);});reader.start();}

Happens-Before

从java5之后,volatile提供了一个Happens-Before的功能。Happens-Before 是指当volatile进行写回主内存的操作时,会将之前的非volatile的操作一并写回主内存。

public class VolatileHappenBeforeUsage {int a = 0;volatile boolean flag = false;public void writer() {a = 1;              // 1 线程A修改共享变量flag = true;        // 2 线程A写volatile变量}
}

上面的例子中,a是一个非volatile变量,flag是一个volatile变量,但是由于happens-before的特性,a 将会表现的和volatile一样。

本文的例子可以参考:https://github.com/ddean2009/learn-java-concurrency/tree/master/volatile

更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程

更多教程请参考 flydean的博客

java中的Volatile关键字使用相关推荐

  1. 如何理解 JAVA 中的 volatile 关键字

    如何理解 JAVA 中的 volatile 关键字 最近在重新梳理多线程,同步相关的知识点.关于 volatile 关键字阅读了好多博客文章,发现质量高适合小白的不多,最终找到一篇英文的非常通俗易懂. ...

  2. Java中的Volatile如何工作? Java中的volatile关键字示例

    如何在Java中使用Volatile关键字 在Java采访中,什么是volatile变量以及何时在Java中使用volatile变量是Java 采访中一个著名的多线程采访问题 . 尽管许多程序员都知道 ...

  3. 深入理解Java中的volatile关键字

    在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性.可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized ...

  4. Java中的volatile关键字

    原博文地址:http://www.cnblogs.com/dolphin0520/p/3920373.html 这里只是对上面的博文的一个简单总结,总结如下: volatile变量保证可见性实现 vo ...

  5. 自顶向下彻底理解 Java 中的 volatile 关键字

    标题 neta 自<计算机网络自顶向下> 思维导图 volatile 在 Java 中被称为轻量级 synchronized.很多并发专家引导用户远离 volatile 变量,因为使用它们 ...

  6. Java中不可或缺的关键字「volatile」

    什么是volatile关键字 volatile是Java中用于修饰变量的关键字,其可以保证该变量的可见性以及顺序性,但是无法保证原子性.更准确地说是volatile关键字只能保证单操作的原子性, 比如 ...

  7. java 中violate_Java中的volatile关键字及Cache更新

    Volatile [ˈvɑːlətl],中文解释:反复无常的,易变的,不稳定的. volatile的本意是告诉编译器,此变量的值是易变的,每次读写该变量的值时务必从该变量的内存地址中读取或写入,不能为 ...

  8. 面试:说说Java中的 volatile 关键词?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | Matrix海子 来源 | https://w ...

  9. null在java存在的意义何在,Java并发编程——volatile关键字

    一.volatile是什么 volatile是Java并发编程中重要的一个关键字,被比喻为"轻量级的synchronized",与synchronized不同的是,volatile ...

最新文章

  1. HTMLParser的初步学习
  2. python多线程的几种方法
  3. nginx lua redis 访问频率限制(转)
  4. 使用Windows远程桌面(mstsc)通过RDP协议访问Ubuntu/Debian服务器
  5. 牛客-服务器需求【线段树】
  6. C# Obsolete
  7. arduino 蓝牙示例_Arduino简单实例之八_蓝牙模块
  8. php7 连接mysql插件_php7
  9. 鸿蒙轻内核源码分析:掌握信号量使用差异
  10. 获取div中的内容写法
  11. C++函数内部实现的规则
  12. 概率编程语言(Probabilistic Programming Languages)库 —— edward
  13. pyspark--用法
  14. Lyndon Word学习笔记
  15. python二级考试答案错误_如果name = “全国计算机等级考试二级Python”,以下选项中输出错误的是...
  16. 常用的SEO工具都有哪些呢?5个SEO必备优化工具推荐
  17. XML Schema快速入门(三)语法之复杂类型
  18. netsetman使用教程_NetSetMan配置网络参数教程
  19. python课程设计小结和体会_通用版课程设计心得体会
  20. 单点登录sso认证中心

热门文章

  1. 安卓入门系列-02创建一个项目
  2. linux 文件系统原理 书,发个关于文件系统的书《Linux文件系统剖析》
  3. 给Source Insight做个外挂系列之六--“TabSiPlus”的其它问题
  4. 1_2 AbstractFactoryMode 抽象工厂模式
  5. 使用 ebpf 深入分析容器网络 dup 包问题
  6. 网络协议,我明明学过的呀?
  7. 曹大带我学 Go(8)—— 一个打点引发的事故
  8. 争做RTC领域标杆——与华为云副总裁薛浩聊聊我们的视频时代
  9. 深度学习在AEC中的应用探索
  10. 【大会】编码、画质评价与网络协议的未来