极简计算机发展史

我们知道,计算机CPU和内存的交互是最频繁的,内存是我们的高速缓存区。而刚开始用户磁盘和CPU进行交互,CPU运转速度越来越快,磁盘远远跟不上CPU的读写速度,才设计了内存,但是随着CPU的发展,内存的读写速度也远远跟不上CPU的读写速度,因此,为了解决这一矛盾,CPU厂商在每颗CPU上加入了高速缓存,用来缓解这种症状,因此,现在CPU同内存交互就变成了下面的样子。

单核CPU的性能不可能无限制的增长,要想很多的提升新能,需要多个处理器协同工作。 基于高速缓存的存储交互很好的解决了处理器与内存之间的矛盾,也引入了新的问题:缓存一致性问题。在多处理器系统中,每个处理器有自己的高速缓存,而他们又共享同一块内存(下文成主存,main memory 主要内存),当多个处理器运算都涉及到同一块内存区域的时候,就有可能发生缓存不一致的现象。为了解决这一问题,需要各个处理器运行时都遵循一些协议,在运行时需要用这些协议保证数据的一致性。

缓存一致性协议中最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。它核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存设置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中该变量是无效状态,那么它就会从内存重新读取

Java内存模型

Java的内存模型和上面的结构还是挺相似的,此时在看工作内存和主内存关系,从逻辑上,高速缓存对应工作内存,每个线程分配到CPU时间片时,独自享有高速缓存的使用能力。主内存对应存储的物理内存。特别注意,这只是逻辑上的对等关系,物理的上具体对应关系十分复杂,这里不讨论。

volatile的作用是什么

volatile可以保证可见性,有序性,但不能保证原子性

可见性

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

假如说有2个线程对一个变量data进行操作,线程先会把主内存中的值缓存到工作内存,这样做的原因和上面提到的高速缓存类似,提高效率

但是这样会引入新的问题,假如说线程A把data修改为1,线程A的工作内存data值为1,但是主内存和线程B的工作内存data值为0,此时就有可能出现Java并发编程中的可见性问题

举个例子,如下面代码,线程A已经将flag的值改变,但是线程B并没有及时的感知到,导致一直进行死循环

输出为,线程B一直没有结束

但是如果将data定义为如下形式,线程A对data的变更,线程B立马能感知到

输出为

那么是如何实现的呢?其实volatile保证可见性的方式和上面提到的缓存一致性协议的原理很类似

线程A将工作内存的data更改后,强制将data值刷回主内存

如果线程B的工作内存中有data变量的缓存时,会强制让这个data变量缓存失效

当线程B需要读取data变量的值时,先从工作内存中读,发现已经过期,就会从主内存中加载data变量的最新值了

放个图理解的更清楚

有序性

有序性即程序执行的顺序按照代码的先后顺序执行

上面代码定义了一个int型变量,定义了一个boolean类型变量,然后分别对两个变量进行赋值操作。从代码顺序上看,语句1是在语句2前面的,那么JVM在真正执行这段代码的时候会保证语句1一定会在语句2前面执行吗?不一定,为什么呢?这里可能会发生指令重排序(Instruction Reorder)。

下面解释一下什么是指令重排序,一般来说,处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的。

比如上面的代码中,语句1和语句2谁先执行对最终的程序结果并没有影响,那么就有可能在执行过程中,语句2先执行而语句1后执行。

但是有依赖关系的语句不会进行重排序,如下面求圆面积的代码

程序的执行顺序只有下面这2个形式

A->B->C和B->A->C,因为A和C之间存在依赖关系,同时B和C之间也存在依赖关系。因此最终执行的指令序列中C不能被重排序到A和B前面。

虽然重排序不会影响单个线程内程序执行的结果,但是多线程呢?下面看一个例子

上面代码中,由于语句1和语句2没有数据依赖性,因此可能会被重排序。假如发生了重排序,在线程1执行过程中先执行语句2,而此是线程2会以为初始化工作已经完成,那么就会跳出while循环,去执行doSomethingwithconfig(context)方法,而此时context并没有被初始化,就会导致程序出错。

从上面可以看出,指令重排序不会影响单个线程的执行,但是会影响到线程并发执行的正确性

当写双重检测锁定版本的单例模式时,就要用到volatile来保证可见性

计算机方向关键字,从计算机的角度理解volatile关键字相关推荐

  1. 【Java线程】深入理解Volatile关键字和使用

    目录 背景 volatile原理 volatile特性 可见性 有序性 原子性 使用场景 背景 理解volatile底层原理之前,首先介绍关于缓存一致性协议的知识. 背景:计算机在执行程序时,每条指令 ...

  2. 对精致码农大佬的 [理解 volatile 关键字] 文章结论的思考和寻找真相

    一:背景 1. 讲故事 昨天在园里的编辑头条看到 精致码农大佬 写的一篇题为:[C#.NET 拾遗补漏]10:理解 volatile 关键字 (https://www.cnblogs.com/will ...

  3. 深入理解volatile关键字---缓存一致性原理

    volatile关键字与缓存一致性 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java ...

  4. [C#.NET 拾遗补漏]10:理解 volatile 关键字

    要理解 C# 中的 volatile 关键字,就要先知道编译器背后的一个基本优化原理.比如对于下面这段代码: public class Example {public int x;public voi ...

  5. 理解volatile关键字

    一. volatile的作用 1. 可见性 cpu 在变量赋值之后加上写屏障,使得对 volatile变量 以及之前变量的写都写入到主内存中 cpu 在变量读取之前加上读屏障,使得对 volatile ...

  6. java中volatile关键字的含义_java中volatile关键字的含义

    转自:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 在java线程并发处理中,有一个关键字volatile的使用目前存 ...

  7. java中volatile关键字的含义_Java里volatile关键字是什么意思

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

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

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

  9. volite java_如何理解 JAVA volatile 关键字

    最近在重新梳理多线程,同步相关的知识点.关于 volatile 关键字阅读了好多博客文章,发现质量高适合小白的不多,最终找到一篇英文的非常通俗易懂.所以学习过程中顺手翻译下来,一方面巩固知识,一方面希 ...

  10. volatile关键字之全面深度剖析

    引言 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字 ...

最新文章

  1. php5.4 mysql connect,php5.4 Call to undefined function mysql_connect()
  2. c语言模拟考试题目,10道C语言笔试模拟题
  3. 隐藏17年的Office远程代码执行漏洞(CVE-2017-11882)
  4. 一个爬虫的demo,requests,beatuifulsoup使用的
  5. Jon Person教你如何用.NET/.NETCF写GPS应用程序。
  6. PIC单片机 按键检测识别
  7. 就在刚刚!吴恩达的这门新课程终于开放注册了
  8. python图像几何变换_Python 图像处理 OpenCV (5):图像的几何变换
  9. hashMap 底层原理+LinkedHashMap 底层原理+常见面试题
  10. Auto.js 全命令整理(三) 输出专题
  11. pat 1006. 换个格式输出整数 (15)
  12. Web前端开发最佳实践(7):使用合理的技术方案来构建小图标
  13. CentOS 7.2 rpm 安装 Mysql 5.7
  14. 计算机网络 --- 网络编程
  15. php集成腾讯云im
  16. HDU5391米勒拉宾
  17. 机器学习Class 6:分类及描述
  18. AXURE RP8实战手册 网站和APP原型制作案例精粹
  19. 面试和谈薪技巧及如何避开常见的陷阱
  20. Centos7初始化网络配置

热门文章

  1. 写项目文档比写代码难多了
  2. 自动生成数据同步存储过程的存储过程
  3. 网络异步编程(C#)团购课
  4. php连接oracle设定字符集,避免乱码
  5. wait方法为什么要放在循环里
  6. vue.js中的路由vue-router2.0使用
  7. spring ORM管理
  8. 调试内核Ubuntu 搭建嵌入式开发环境-续
  9. Shell脚本应用之服务启动脚本
  10. 怎样查看域名DNS服务器的相一些关信息