voliate关键字详解:

1.内存模型相关概念

物理计算机内存访问图:

任何计算都是在CPU内处理的,那么也就必须涉及到数据读写,但是CPU每次都要和主内存交互读写数据效率太低了,于是有了高速缓存。在程序运行时,会从主内存中复制一份数据到高速缓存中,然后CPU在高速缓存中读写数据,计算完成后,再将结果从高速缓存中返回到主内存里。
在单线程中,上述操作是不会有问题的,但在多线程中就不行了
例如我们让两个线程都进行a=a+1的操作,按常理来说,结果会是2,但是有一下一种情况:
线程1和线程2都从主内存中读数据到高速缓存中,此时他们读的都是a一开始等于0的情况,然后分别在CPU中运算,线程1完成后,将结果a=1返回到主内存中。线程2完成运算后从高速内存将结果返回,还是a=1。那么结果就是两个线程分别做了加一运算,但是结果为1。
也就是说,一个变量在多个CPU中都有缓存就会出现:缓存不一致问题

2.Java内存模型

JMM(Java Memory Model)图:
工作内存其实是缓存、寄存器、编译器优化等笼统概念。

Java内存模型规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(类似于前面的高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。
这个图可以和物理计算机内存图类比,也会存在缓存不一致问题,并且Java中没有限制编译器为了提高效率对指令进行重排序,所以也会出现指令重排序问题

2.voliate关键字作用

为了解决Java缓存不一致和重排序问题,于是有了voliate关键字。
当一个共享变量被voliate修饰后

  1. 保证了这个变量再不同线程的可见性,一个线程修改了它,另一个线程立马知道
  2. 禁止指令重排序

前面说了,CPU会在缓存中读写数据,那么加了voliate关键字之后:

  1. 会将结果值立马写入主存
  2. 使其他线程对应变量的缓存无效,所以需要再次去主存中读取

我们用一段代码理解一下:

static class Counter {public int flag = 0;
}
public static void main(String[] args) {Counter counter = new Counter();Thread t1 = new Thread(() -> {while (counter.flag == 0) {// do nothing}System.out.println("循环结束!");});Thread t2 = new Thread(() -> {Scanner scanner = new Scanner(System.in);System.out.println("输入一个整数:");counter.flag = scanner.nextInt();});t1.start();t2.start();
}

t1线程会一直循环,t2线程会让用户输入一个整数,当用户输入0以外的值时,欲使t1线程循环结束。
但是执行结果是:输入5,t1线程仍在循环。
原因就是我们刚才所说的,t1线程一直读取的是工作内存的数据,工作内存中的flag任然是0,它没有意识到主存中flag的值已经为5了。
那么我们给flag用以voliate关键字修饰之后,就不会出现问题了。t2线程修改了flag值后会马上写入主存,t1线程工作内存的flag缓存会马上作废,从主存中读取flag的新值。

voliate不能保证原子性,它保证了内寸可见性和一定程度上的有序性
一定程度上的有序性是什么意思?
就是说加了voliate修饰的变量,对它的值进行修改的代码行相对位置不会变,不会受到指令重排序的影响
比如:
a,b,c,d没有被voliate关键字修饰
flag被voliate关键字修饰了

a=1;
b=2;
flag=5;
c=4;
d=6;

那么flag的位置一定会在a,b和c,d之间夹着。但是a,b的顺序可能调换,c,d的顺序也可能调换,所以是一定程度上的有序性。

voliate关键字相关推荐

  1. java中变量 关键字_基于java的voliate关键字详解

    voliate关键字的作用: 一.内存可见性 基于缓存一致性协议,当用voliate关键字修饰的变量改动时,cpu会通知其他线程,缓存已被修改,需要更新缓存.这样每个线程都能获取到最新的变量值. 二. ...

  2. voliate关键字原理

    被volatile修饰的变量在编译成字节码文件时会多个lock指令,该指令在执行过程中会生成相应的内存屏障,以此来解决可见性跟重排序的问题. 预备知识 指令重排序 为什么到指令重排序:一般来说,处理器 ...

  3. 关于voliate关键字

    现象 private static boolean is = false;public static void main(String[] args) {new Thread(new Runnable ...

  4. C++中voliate关键字

    voliate变量是随时变化的,用voliate修饰的运算,编译器不进行优化,以免出错. 对于一个普通变量,为提高存取速率,编译器会先将变量的值存储在一个寄存器中,以后再取变量值时,就存寄存器中取出. ...

  5. C语言中voliate关键字的作用

    一个变量用voliate关键字修饰,是要告诉编译器,这个变量的值随时可能发生变化,所以编译器每次都必须从变量对应的内存地址中获取该变量的值. voliate的常用方式: 当一个变量表示某寄存器的值时, ...

  6. Voliate关键字的作用

    Voliate关键字主要有以下两个作用: 一:内存可见性 基于缓存一致性协议,当系统或者程序中某个变量发生修改时,此时cpu会同时其他线程,告诉被通知的线程缓存内容已经被修改,通知i线程需要更新缓存, ...

  7. 多线程 - voliate 关键字

    介绍 volatile 是 Java 中的关键字,用于修饰变量.它的作用是强制对被修饰的变量的写操作立即刷新到主存中,并强制对该变量的读操作从主存中读取最新的值,而不是使用缓存中的值. 作用 保证变量 ...

  8. java voliate关键字_java中voliate关键字有什么用?

    1.保证内存可见性 内存可见性,即线程A对volatile变量的修改,其他线程获取的volatile变量都是最新的. 说到内存可见性就必须要提到Java的内存模型,如下图所示: 如上图所示,所有线程的 ...

  9. voliate 关键字

    voliate cpu术语定义 术语 英文单词 术语描述 内存屏障 cache barriers 处理器的指令 , 用于实现对内存操作的顺序限制 原子操作 atomic opers 不可中断的一个操作 ...

最新文章

  1. DPM全方位保护SQL Server,DPM2007系列之五
  2. php txt删除重复行,php – 删除文本文件中的重复行
  3. DHTML之-----document.selection 的 createRange
  4. 【渝粤教育】广东开放大学 土木工程材料 形成性考核 (22)
  5. Java LocalDate类| toString()方法与示例
  6. 1000道Python题库系列分享24(41个客观题,numpy专题)
  7. 浅谈混合精度训练imagenet
  8. Rust:命令行参数与环境变量操作
  9. 结构梁配筋最牛插件_结构工程师应该了解的一些基本概念知识
  10. 如何深入学习c语言,如何深入学习C语言?
  11. Log4j2 0day漏洞项目级紧急修复方法
  12. 保姆级的接口自动化教程,不会写代码也能2小时学会
  13. MS2131 USB 3.0 高清音视频采集+ HDMI 环出+混音处理芯片
  14. GMap.NET控件使用
  15. 301代码php代码在哪里加,php 301转向实现代码
  16. 图片转PDF格式怎么弄?我来教你几个方法
  17. Android肝帝战纪之ObjectBox移动数据库框架探究与实现
  18. UVA 10859 放置街灯(树形DP)
  19. 深入浅出FPGA-4-数字电路设计基础
  20. 微型计算机BX和AX区别,微机原理及接口技术-习题答案

热门文章

  1. bootstrap-loader使用过程中遇到的几个坑爹问题
  2. fiddler4手机安装证书失败解决教程
  3. 元旦去峨眉山吧,人间值得
  4. for the love of god
  5. echarts中series下的data循环拼接
  6. 咚咚咚————【封装驱动】W25QXX全系列驱动程序,分享交流自己编写的程序。
  7. 百度空间部分表单查询
  8. 科学计算用数字电子计算机,关于科学计算用数字电子计算机字长问题-计算机工程与科学.PDF...
  9. 第十九篇玩转【斗鱼直播APP】系列之内容简介
  10. pyqtgraph绘制图:使用PyQtGraph绘制图形的6种方法