点击上方 好好学java ,选择 星标 公众号

重磅资讯、干货,第一时间送达
今日推荐:有了这 4 款工具,老板再也不怕我写烂SQL了个人原创+1博客:点击前往,查看更多
作者:对弈
来源:https://www.cnblogs.com/MessiXiaoMo3334/p/12615823.html

volatile是Java虚拟机提供的轻量级的同步机制(“乞丐版”的synchronized)

  1. 保证可见性

  2. 不保证原子性

  3. 禁止指令重排

可见性

指当多个线程访问同一个变量时,如果其中一个线程修改了这个变量的值,其他线程能够立即看得到修改的值

验证可见性demo:

import java.util.concurrent.TimeUnit;class MyData {volatile int number = 0;public void addTo60() {number = 60;}
}
public class VolatileDemo {public static void main() {MyData myData = new MyData();new Thread(() -> {System.out.println(Thread.currentThread().getName() + "\t come in");try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}myData.addTo60();System.out.println(Thread.currentThread().getName() + "\t updated number: " + myData.number);}, "AAA").start();while (myData.number == 0) {}System.out.println(Thread.currentThread().getName() + "\t mission is over");}
}

结果:

AAA  come in
main     mission is over
AAA  updated number: 60

不保证原子性

原子性:程序中的所有操作是不可中断的,要么全部执行成功要么全部执行失败

不保证原子性正是volatile轻量级的体现,多个线程对volatile修饰的变量进行操作时,会出现容易出现写覆盖的情况(i++)

验证不保证原子性demo:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;class MyData {volatile int number = 0;public void addPlusPlus() {number++;}
}
public class VolatileDemo {public static void main(String[] args) {MyData myData = new MyData();for (int i = 0; i < 20; i++) {new Thread(() -> {for (int j = 0; j < 1000; j++) {myData.addPlusPlus();}}, String.valueOf(i)).start();}while (Thread.activeCount() > 2) {Thread.yield();}System.out.println(Thread.currentThread().getName() + "\t finally number value: " + myData.number);}
}

结果:

main    finally number value: 19109

解决不保证原子性问题:Atomic

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;class MyData {volatile int number = 0;public void addPlusPlus() {number++;}AtomicInteger atomicInteger = new AtomicInteger();public void addAtmic() {atomicInteger.getAndIncrement();}
}
public class VolatileDemo {public static void main(String[] args) {MyData myData = new MyData();for (int i = 0; i < 20; i++) {new Thread(() -> {for (int j = 0; j < 1000; j++) {myData.addAtmic();}}, String.valueOf(i)).start();}while (Thread.activeCount() > 2) {Thread.yield();}System.out.println(Thread.currentThread().getName() + "\t finally number value: " + myData.number);System.out.println(Thread.currentThread().getName() + "\t AtomicInteger type,finally number  value: "+ myData.atomicInteger);}
}

结果:

main     finally number value: 19746
main     AtomicInteger type,finally number  value: 20000

禁止指令重排

指令重排:为了提高程序运行效率,编译器可能会对输入指令进行重新排序,即程序中各个语句的执行先后顺序同代码中的顺序不一定一致。(但是它会保证单线程程序最终执行结果和代码顺序执行的结果是一致的,它忽略了数据的依赖性

源代码 -> 编译器优化重排 -> 指令并行重排 -> 内存系统重排 -> 最终执行指令

volatile能够实现禁止指令重排的底层原理:

  • 内存屏障(Memory Barrier):它是一个CPU指令。由于编译器和CPU都能够执行指令重排,如果在指令间插入一条Memory Barrier则会告诉编译器和CPU,任何指令都不能和该条Memory Barrier指令进行重排序,即通过插入内存屏障指令能够禁止在内存屏障前后的指令执行重排序 优化

  • 内存屏障的另外一个作用是强制刷新各种CPU的缓存数据,因此任何CPU上的线程都能够读取到这些数据的最新版本。以上两点正好对应了volatile关键字的禁止指令重排序和内存可见性的特点

  • 对volatile变量进行写操作时,会在写操作之后加入一条store屏障指令,将工作内存中的共享变量copy刷新回主内存中;对volatile变量进行读操作时,会在读操作之前加入一条load的屏障指令,从主内存中读取共享变量

应用场景:

  • 高并发环境下DCL单例模式使用volatile

public class SingletonDemo {private static volatile SingletonDemo instance = null;private SingletonDemo() {System.out.println(Thread.currentThread().getName() + "我是构造方法SingletonDemo()");}public static SingletonDemo getInstance() {if (instance == null) {synchronized (SingletonDemo.class) {if (instance == null) {instance = new SingletonDemo();}}}return instance;}public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {SingletonDemo.getInstance();}, String.valueOf(i)).start();}}}
  • JUC包下AtomicXxx类:原子类AtomicXxx中都有一个成员变量value,该value变量被声明为volatile,保证 AtomicXxx类的内存可见性,而原子性由CAS算法&Unsafe类保证,结合这两点才能让AtomicXxx类很好地替代synchronized关键字。

public class AtomicInteger extends Number implements java.io.Serializable {// ...private volatile int value;// ...}

一文读懂 volatile 关键字相关推荐

  1. 一文搞懂Volatile关键字的作用

    前言 Volatile关键字的作用主要有如下两个: 1.线程的可见性:当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值. 2. 顺序一致性:禁止指令重排序. 一.线程可见性 我们先通过一个 ...

  2. 【Java基本功】一文读懂final关键字的用法

    本文主要介绍了final关键字的基本使用方法及原理 final关键字可以修饰类.方法和引用. 修饰类,该类不能被继承.并且这个类的对象在堆中分配内存后地址不可变. 修饰方法,方法不能被子类重写. 修饰 ...

  3. 【Java基本功】一文读懂final关键字的用法 1

    本文主要介绍了final关键字的基本使用方法及原理 final关键字可以修饰类.方法和引用. 修饰类,该类不能被继承.并且这个类的对象在堆中分配内存后地址不可变. 修饰方法,方法不能被子类重写. 修饰 ...

  4. C++ ——一文读懂:关键字override

    override在C++中它是覆盖了一个方法并且对其重写,从而达到不同的作用.在我们C++编程过程中,最熟悉的就是对接口方法的实现,在接口中一般只是对方法进行了声明,而我们在实现时,就需要实现接口声明 ...

  5. 前端面试必会 | 一文读懂 JavaScript 中的 this 关键字

    this 是一个令无数 JavaScript 编程者又爱又恨的知识点.它的重要性毋庸置疑,然而真正想掌握它却并非易事.希望本文可以帮助大家理解 this. JavaScript 中的 this Jav ...

  6. java中date类型如何赋值_一文读懂java中的Reference和引用类型

    简介 java中有值类型也有引用类型,引用类型一般是针对于java中对象来说的,今天介绍一下java中的引用类型.java为引用类型专门定义了一个类叫做Reference.Reference是跟jav ...

  7. mysql 默认事务隔离级别_一文读懂MySQL的事务隔离级别及MVCC机制

    回顾前文: <一文学会MySQL的explain工具> <一文读懂MySQL的索引结构及查询优化> (同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论 ...

  8. 从根上理解高性能、高并发(七):深入操作系统,一文读懂进程、线程、协程

    本文引用了"一文读懂什么是进程.线程.协程"一文的主要内容,感谢原作者的无私分享. 1.系列文章引言 1.1 文章目的 作为即时通讯技术的开发者来说,高性能.高并发相关的技术概念早 ...

  9. 一文读懂Java中File类、字节流、字符流、转换流

    一文读懂Java中File类.字节流.字符流.转换流 第一章 递归:File类: 1.1:概述 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. ...

最新文章

  1. 【Hadoop Summit Tokyo 2016】Rakuten是如何解决由于大规模多租户Hadoop集群造成的迷之问题的...
  2. *:教育产品 规范销售
  3. Java-toString
  4. 软件测试中一个BUG的生命周期
  5. TokenInsight:反映区块链行业整体表现的TI指数较昨日同期上涨0.54%
  6. Win10值得推荐的软件,提升效率和桌面美观
  7. Android Gradle Build Error:Some file crunching failed, see logs for details解决办法
  8. 厚物科技PXIe机箱PXI机箱PXIe便携机HW-1693BAT
  9. 《国富论》阅读笔记03
  10. ARVR | AR技术发展简史(上)
  11. postman--常用公共函数
  12. html5禁止浏览器缩放网页大小 (实用)
  13. vue-admin websocket接收消息推送+语音提示(详细代码)
  14. java 绘制动态的图形
  15. java 跨域 cookie_跨域请求传递Cookie问题
  16. 分享一个新软件 云端软件平台+个人使用心得
  17. Qt第三方图形控件qwt的编译安装与使用的简单方法(Win7+Qt4.8.6+MinGW4.8.2)
  18. 2021年度总结——似乎除了认真学习,其他的事情我都干了……
  19. 运维Ansible自动化工具概述
  20. mysql的for update详解

热门文章

  1. 恢复误删数据(SQL Server 2000)--Log Explorer
  2. Microsoft SharePoint Portal Server 2003 订制开发研讨(流水帐)
  3. ESP32 flash容量配置
  4. stm32多块开发板can总线互联卡死问题
  5. JavaScript定时器原理及高级使用
  6. 波卡链Substrate (7)Grandpa + Babe
  7. C++ Primer 5th笔记(chap 17 标准库特殊设施)随机数
  8. EOS 智能合约源代码解读 (4)symbol.hpp
  9. Bitcoin0.21版 公链开发(4) Apache windows上安装
  10. 《图解密码技术》分组密码(5) 输出反馈OFB模式