要想学好JUC,还得先了解 volatile 这个关键字。了解 volatile ,我们从一个例子开始吧。

本文不会很详细去说java内存模型,只是很简单地学习一下volatile

一个例子

  1. package jfound.demo;
  2. import java.util.concurrent.TimeUnit;
  3. public class TaskRunner {
  4. private static boolean ready = true;
  5. public static void main(String[] args) throws InterruptedException {
  6. new Thread(() -> {
  7. while (ready) {
  8. }
  9. }).start();
  10. TimeUnit.SECONDS.sleep(1);
  11. ready = false;
  12. }
  13. }

这个程序里面,新开一个线程,ready 初始化值为true, 线程里面是一个死循环,当 ready 修改为 false的时候,我们希望线程里面的死循环会结束,然后jvm会停止。

然后在这个例子里面,程序根本不会停止。但当 readyvolatile 关键字修饰的时候,程序符合我们预期,停止了。

  1. ....
  2. private static volatile boolean ready = true;
  3. ...

CPU执行及缓存

CPU负责执行程序指令,但是他们需要从内存(RAM)中获取程序指令和所需要的数据。由于CPU每秒能执行大量的执行,如果每执行一次指令就从内存(RAM)中获取数据的话,显然是不够理想的,毕竟CPU与内存之间还是有一定的距离的。为了改善这种情况,CPU会有一系列的优化,例如指令重排序,当然,还有缓存。下图为CPU及内存层次的结构。

当CPU获取指令的时候,也会把指令所需要的数据读进CPU缓存中,当在某些时刻,通常是指令改变或者缓存失效时,CPU会重新从内存(RAM)中读取指令或数据。

在上面的例子中,新开的线程在做循环的时候,会读取 ready 变量到该线程所执行的CPU缓存中,当 main 线程修改 ready 变量为 false 的时候,是首先写在 main 线程所执行的CPU的缓存中,在某些时刻才会写入到内存(RAM)中。也就是说要让新开的线程停止的话,必须是 main 线程修改的变量写入到内存(RAM)中,而且新开的线程的所在的CPU缓存要失效,让其重新读取 ready 变量。然而,没有加 volatile 之前,main 线程并不会实时把变量 ready 写入到内存(RAM)中去,新开的线程也不会从内存中获取 ready 新的数据。

缓存一致性协议(MESI协议)

上述的问题就是大名鼎鼎的缓存不一致性的问题,也就是在并发编程中所要解决的主要问题之一。

在早期的CPU中,是通过在总线(上图中的Bus)上加LOCK#的形式来解决缓存不一致的问题,当加上总线锁的时候,加锁的CPU就独占内存,其他CPU就不能读取内存,也就是不能执行指令,只能乖乖等待锁释放,这样的总线锁效率很低,不过是能解决了缓存不一致的问题。

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

MESI全名是Modified、Exclusive、 Share or Invalid,使每一个缓存行可能处于M、E、S和I这四种状态之一,

  • M:被修改的。处于这一状态的数据,只在本CPU中有缓存数据,而其他CPU中没有。同时其状态相对于内存中的值来说,是已经被修改的,且没有更新到内存中。
  • E:独占的。处于这一状态的数据,只有在本CPU中有缓存,且其数据没有修改,即与内存中一致。
  • S:共享的。处于这一状态的数据在多个CPU中都有缓存,且与内存一致。
  • I:无效的。本CPU中的这份缓存已经无效。

例子解析

volatile 关键字有着上面所说的触发缓存一致性的功能,所以在加上 volatile 关键字之后,main 线程把 ready 修改为 false 的时候,新开的线程是可以读取到修改后的 ready 的值,所以程序是可以符合我们的预期,停止了。

总结

本文通过上面的一个小例子来解析了 volatile 的一个功能,缓存一致性,为接下来学习 JUC 做准备。当然 volatile 关键字在java中还会有其他的功能,例如 happer-before、内存屏障、重排序等等,这些就不在本文赘述了。

微信关注我,发现更多java领域知识

JUC整理笔记二之聊聊volatile的更多相关文章

  1. JUC整理笔记一之细说Unsafe

    JUC(java.util.concurrent)的开始,可以说是从Unsafe类开始. Unsafe 简介 Unsafe在sun.misc 下,顾名思义,这是一个不安全的类,因为Unsafe类所操作 ...

  2. JUC整理笔记三之测试工具jcstress

    并发测试工具Jcstress使用教程 Jcstress 全称 Java Concurrency Stress,是一种并发压力测试工具,可以帮助研究JVM.java类库和硬件中并发的正确性. Wiki地 ...

  3. jQuery整理笔记文件夹

    jQuery整理笔记文件夹 jQuery整理笔记一----jQuery開始 jQuery整理笔记二----jQuery选择器整理 jQuery整理笔记三----jQuery过滤函数 jQuery整理笔 ...

  4. JUC学习笔记(二)

    JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html 1.Lock接口 1.1.Synchronized 1.1.1.Synchronized关 ...

  5. canvas学习之API整理笔记(二)

    前面我整理过一篇文章canvas学习之API整理笔记(一),从这篇文章我们已经可以基本了解到常用绘图的API.简单的变换和动画.而本篇文章的主要内容包括高级动画.像素操作.性能优化等知识点,讲解每个知 ...

  6. JUC学习笔记(四)

    JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html JUC学习笔记(二)https://www.cnblogs.com/lm66/p/1511 ...

  7. xmpp整理笔记:发送图片信息和声音信息

    图片和音频文件发送的基本思路就是: 先将图片转化成二进制文件,然后将二进制文件进行base64编码,编码后成字符串.在即将发送的message内添加一个子节点,节点的stringValue(节点的值) ...

  8. xmpp整理笔记:聊天信息的发送与显示

    任何一个信息的发送都需要关注两个部分,信息的发出,和信息在界面中的显示 往期回顾: xmpp整理笔记:环境的快速配置(附安装包)  http://www.cnblogs.com/dsxniubilit ...

  9. xmpp整理笔记:用户网络连接及好友的管理

    xmpp中的用户连接模块包括用户的上线与下线信息展现,用户登录,用户的注册: 好友模块包括好友的添加,好友的删除,好友列表的展示. 在xmpp中 负责数据传输的类是xmppStream,开发的过程中, ...

随机推荐

  1. TreeMap分析(中)

    通过上篇文章,大家已经能够理解红黑树的基础数据结构,那么这篇文章就来分析下,在红黑树中插入一个结点后,内部数据结构发生了哪些变化. TreeMap插入某个结点的源码分析 /** * 插入节点,并平衡红 ...

  2. 家用PC机打造VSphere5.1 测试环境:之部署VCenter Server 5.1

    家用PC机打造VSphere5.1 测试环境前言:实践出真知,同样学习VMware VSphere 的朋友,也需要不断的测试总结,再测试再总结只有不断的积累才能学好,但是动辄几万的服务器不是所有朋友都 ...

  3. OpenCV的安装和使用

    @ windows系统 (环境:VS2013) 下载安装opencv.exe: VS2013下“项目”->“属性页”->“配置属性”-> “VC++目录”: 包含目录 - ..\op ...

  4. #Week1 Introduction

    一.What is Machine Learning 课程里主要给了两个供参考的定义: By Arthur Samuel: Field of study that gives computers th ...

  5. 软件——Ubuntu16.04设置静态ip地址

    1.获取网卡名称 在命令行输入ifconfig -a 2.修改网卡配置文件 sudo vim /etc/network/interfaces 加上下面的配置,IP地址可以成适合你的 auto eth0 ...

  6. C语言程序设计实验报告(第一次实验)

    C程序设计实验报告 实验项目:C语言程序设计教程实验1.3.2:1.3.3:1.3.4:2.3.1:2.3.2 姓名:赖瑾 实验地点:家 实验时间:2020.2.25 目录 C程序设计实验报告 一.实 ...

  7. E. Height All the Same

    E. Height All the Same 题目大意: 给你一个n*m 的矩阵,让你在里面填数字代表这个位置的高度,数字的范围是[L,R],有两种操作,第一种就是给一位置的高度加2,第二种就是给两个 ...

  8. mui指南

    转自https://www.cnblogs.com/koleyang/p/5146623.html http://dev.dcloud.net.cn/mui/ui/index.html#mask ht ...

  9. Spring Cloud学习 之 Spring Cloud Ribbon(执行流程源码分析)

    Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 文章目录 分析: 总结: 分析: ​ 在上篇文章中,我们着重分析了RestTempla ...

  10. Json格式数据的解析

    JSON是一种轻量级的数据交换格式,我们在编程中遇到的JSON数据通常就是一串字符串,只不过按照特定的格式去书写,这样当你把JSON数据传输给别人的时候对方只要使用这种特定的规则去阅读解析你的数据即可 ...