volatile关键字介绍,要了解volatile需要了解的还有Java内存模型,以及CPU内存模型等知识。首先从CPU和Java内存模型开始说起。

CPU Cache模型

  在之前的时候,分享过一个博客一篇博客,就是关于介绍CPU与内存速度不匹配的问题,为了解决这个问题,在CPU和内存之间设计了高速缓存,这个高速缓存出现就是解决CPU和RAM主存之间的速度不匹配。现在CPU的缓存已经增加到了三层。其中最靠近CPU的缓存称为L1,然后依次是L2,L3和主内存。


  Cache的出现是为了解决CPU直接访问内存效率低下的问题,在程序运行的过程中会将运算需要的数据从主存中复制一份到CPUCache中,这样的话CPU就可以直接对CPUCache中的数据进行读写操作。计算结束之后将结果刷新到主存中,CPU直接访问Cache提高了访问的速度,提高提升了效率。

CPU缓存一致性问题

  缓存的出现提升了CPU的运算效率,同时也出现了缓存不一致的问题,例如i++操作,在程序运行的过程中,首先将主存中的数据复制一份到CPU Cache中,然后从CPU缓存进行读写操作。

  1. 读取 主存中的 i 到 Cache
  2. 对Cache中的 i 进行加 1 操作
  3. 然后将结果写回到Cache中
  4. 将结果重新刷新到主存中

这样的操作在单线程的情况下是没有任何问题的,但是在多线程的情况下就会出现问题,因为我们知道多线程每个线程都会有自己的工作内存(这个可以参考Java内存模型)对于变量 i 来说在每个线程的本地内存中都会有一个对应Cache缓存中的结果。这样多个线程同时访问就会出现缓存不一致的问题。为了解决这个问题提出了两种解决方案
1.通过总线加锁的方式
2.通过缓存一致性协议

第一种方式通常存在于CPU中,是一种悲观的方式实现,CPU和其他组件的通信都是通过总线来实现的(这个在计算机组成原理中有过对应的介绍)。如果采用总线的方式会一个组件进行操作,会阻塞其他组件的操作。
第二种方式是通过缓存一致性协议的方式来解决。

缓存一致性协议使用最多的就是Intel的MESI协议,MESI协议保证了每一个缓存中使用共享变量都是一致的。大致思想是当CPU在操作Cache中的数据时候,如果发现这个变量为一个共享变量,也就是说在其他的Cache中也存在一个副本。具体操作
1.读操作。不做任何处理,只将Cache中的数据读取到寄存器中
2.写入操作,发送信号通知其他CPU将变量Cache line设置为无效状态,其他的CPU进行操作的时候不得从主存中再次获取

Java内存模型

  Java内存模型(Java Memory Mode,JMM)指定了Java虚拟机如何使用计算机的主存进行工作。如下图,可以看到每个线程都会有自己对应的操作内存,当然从JDK1.5开始使用JVM对虚拟机内存进行了新的定义。Java内存模型也定义了线程与主存之间的抽象对应关系。

  1. 共享变量都存储在主内存中,可以被任意一个线程访问
  2. 每个线程都有私有的工作内存,本地内存
  3. 工作内存只存储该线程对应的共享变量副本
  4. 线程不会直接操作主内存,是通过直接写到线程本地内存中,然后进入主内存
  5. 线程的工作内存与虚拟机内存模型一样,是一个抽象的概念。并不是真实存在的。

Java内存模型是一个抽象的概念,因为是个虚拟机的概念,所以与真实的硬件的内存并不完全一样,所以无论是JVM的堆内存和栈内存都会与计算机主内存进行对应。当然还有一部分的内存与Cache对应。如下图所示。

总结

  以上主要是对CPU内存模型和JVM内存模型做了一定的介绍。为使用volatile关键字提出了一个概念上的理解,相比较于之前的概念,这个概念是理解起来比较困难的。所以要理解起来还是需要一定的时间。但是真正理解了这个也是比较容易的,主要要对JVM内存模型有一定的了解。这里提供一个链接https://blog.csdn.net/nihui123/article/details/89527876,和一张图。有助于对本篇文章的理解。

Java高并发编程详解系列-内存模型相关推荐

  1. Java高并发编程详解系列-Java线程入门

    根据自己学的知识加上从各个网站上收集的资料分享一下关于java高并发编程的知识点.对于代码示例会以Maven工程的形式分享到个人的GitHub上面.   首先介绍一下这个系列的东西是什么,这个系列自己 ...

  2. Java高并发编程详解系列-7种单例模式

    引言 在之前的文章中从技术以及源代码的层面上分析了关于Java高并发的解决方式.这篇博客主要介绍关于单例设计模式.关于单例设计模式大家应该不会陌生,作为GoF23中设计模式中最为基础的设计模式,实现起 ...

  3. Java高并发编程详解系列-线程上下文设计模式及ThreadLocal详解

    导语   在之前的分享中提到过一个概念就是线程之间的通信,都知道在线程之间的通信是一件很消耗资源的事情.但是又不得不去做的一件事情.为了保证多线程线程安全就必须进行线程之间的通信,保证每个线程获取到的 ...

  4. Java高并发编程详解系列-类加载

    之前在写关于JVM的时候提到过类加载机制,类加载机制也是在Java面试中被经常问道的一个问题,在这篇博客中就来了解一下关于类加载的知识. 类加载   在JVM执行Java程序的时候实际上执行的编译好的 ...

  5. Java高并发编程详解系列-Future设计模式

    导语   假设,在一个使用场景中有一个任务需要执行比较长的时间,通常需要等待任务执行结束之后或者是中途出错之后才能返回结果.在这个期间调用者只能等待,对于这个结果Future设计模式提供了一种凭据式的 ...

  6. Java高并发编程详解系列-线程安全数据同步

    在多线程中最为复杂和最为重要的就是线程安全.多个线程访问同一个对象的时候会导致线程安全问题.通过加锁可以避免这种问题.但是在串行执行的过程中又不用考虑线程安全问题,而使用串行程序效率低没有办法将CPU ...

  7. Java高并发编程详解系列-不可变对象设计模式

    导语   在开发中涉及到的所有关于多线程的问题都离不开共享资源的存在.那么什么是共享资源,共享资源就是被多个线程共同访问的数据资源,而且每个线程都会引起它的变化.伴随共享资源而生的新问题就是线程安全, ...

  8. Java高并发编程详解系列-ThreadAPI简单说明

    之前的两篇分享中,简单的从概念上和简单的操作上了解了Thread,这篇分享中主要是看看对于Thread的所有API的使用方式,通过解析源码的方式来了解关于Thread的细节的使用方式 引言   首先在 ...

  9. Java高并发编程详解系列-Guarded Suspension设计模式

    导语   什么是Guarded Suspension模式,Suspension 意思是挂起,暂停的.而Guarded则表示担保的意思,连起来的就是确保挂起.也就是说当线程访问某个对象的时候,发现条件不 ...

最新文章

  1. 如何快速的给你的项目添加icon图标
  2. Docker 从入门到精通(建议收藏的教程)
  3. java实现注销登录
  4. uwsgi xml 配置
  5. SAP UI5 应用开发教程之三十二 - 如何创建一个自定义 SAP UI5 控件试读版
  6. Callback模式和Template模式
  7. 常见查找算法(Java代码实现)
  8. 电大计算机应用小抄,2015年最新电大统考计算机应用基础小抄(完整版电大小抄).DOC...
  9. 苹果说:没错,我就是故意让旧 iPhone 变慢的!
  10. coreseek mysql_coreseek (sphinx)+ Mysql + Thinkphp搭建中文搜索引擎详解
  11. 由ViewStateException: The client disconnected想到的
  12. 编译安装httpd 2.4
  13. 描述数据库表关系之间的ER图(1对1,1对多,多对1,多对多等关系)
  14. 贪心算法之田忌赛马问题
  15. Oracle11g在虚拟机win7上的详细安装过程(包括win7在虚拟机上的安装)
  16. vue点击实现箭头的向上与向下
  17. 绑定异常 Invalid bound statement (not found): com.fwind.blog.dao.mapper.TagMapper
  18. 中文检索式问答机器人模型
  19. wireshark抓包测试:海康摄像机
  20. [转帖]流言终结者 —— “SQL Server 是Sybase的产品而不是微软的”

热门文章

  1. c++用什么软件编程_学习编程用什么做笔记比较好?
  2. Expression Design与Blend制作滚动的小球动画教程
  3. JMS Helloworld
  4. 老百姓需要这样的智慧城市
  5. 静态网站优化技巧总结
  6. xcache安装配置
  7. 500 OOPS: vsftpd: refusing to run with writable root inside chroot()
  8. 『线性同余方程和中国剩余定理』
  9. 步步为营 .NET 代码重构学习笔记 十
  10. 安全测试之session,cookie