一、介绍

volatile保证共享变量的“可见性”。可见性指的是当一个线程修改变量时,另一个线程能读到这个修改的值。

这里就要提出几个问题。

  • 问题1:为什么一个线程修改时,另一个线程可能会“看不见”?
  • 问题2:这种可见性是如何实现的?

二、问题1 变量为何“不可见”

回答:是由于缓存导致的可见性问题

2.1 为什么要引入缓存?

是为了解决性能问题。CPU的处理速度远远快于内存的读取速度(CPU与内存之间的瓶颈也叫“冯诺依曼瓶颈”),所以处理器不直接和内存通信,而是设置内部缓存(L1、L2...),内存的数据会读取到内部缓存中,CPU直接从内部缓存中读取数据处理。

2.2 L1、L2、L3有何区别?

L1、L2、L3是CPU三级缓存,CPU缓存的定义为CPU与内存之间的临时数据交换器,它的出现是为了解决CPU运行处理速度与内存读写速度不匹配的矛盾。

读取速度 L1 > L2 > L3

容量大小 L1 < L2 < L3

L1又分为一级数据缓存、一级指令缓存,分别用于存放数据、执行数据的指令解码。

2.3 只管高速缓存中的变量,不管内存中的变量行不行?

多个处理器修改变量写到高速缓存,高速缓存中存储的变量值是最新,下次不管内存中的变量值,直接从高速缓存中获取不就行了?

回答:当然不行。

为什么?因为每个处理器都有自己的高速缓存,一个变量在A处理器的高速缓存中修改,B处理器可能感知不到。

三、问题2 变量如何变为“可见”

为了保证在多处理器下,缓存一致,就设置一个缓存一致的协议。每个处理器通过嗅探在总线传播的数据来检查自己缓存的值是否是过期的。

当处理器发现自己的缓存行对内的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当需要对数据进行修改时,重新从内存中读到高速缓存中。

3.1 具体是如何实现?

当变量被volatile修饰,编译成汇编时,会增加一个Lock前缀指令。

Lock前缀指令的作用:

  • Lock前缀指令,会让处理器缓存回写到内存
  • 一个处理器缓存回写到内存,导致其他处理器的缓存无效

参考文档

[1]: 《Java并发编程的艺术》
[2]: Java并发编程-volatile
[3]: CPU与内存的那些事
[4]: 超能课堂(133):为什么CPU缓存会分为L1、L2、L3?

Java核心复习—— volatile 与可见性的更多相关文章

  1. Java并发:volatile内存可见性和指令重排

    volatile两大作用 1.保证内存可见性 2.防止指令重排 此外需注意volatile并不保证操作的原子性. (一)内存可见性 1 概念 JVM内存模型:主内存和线程独立的工作内存 Java内存模 ...

  2. Java核心复习—— 原子性、有序性与Happens-Before

    一. 产生并发Bug的源头 可见性 缓存导致的可见性问题 原子性 线程切换带来的原子性问题 有序性 编译优化带来的有序性问题 上面讲到了 volatile 与可见性,本章再主要讲下原子性.有序性与Ha ...

  3. Java核心复习——J.U.C AbstractQueuedSynchronizer

    第一眼看到AbstractQueuedSynchronizer,通常都会有这几个问题. AbstractQueuedSynchronizer为什么要搞这么一个类? 这个类是干什么的.有什么用? 这个类 ...

  4. Java核心复习——线程池ThreadPoolExecutor源码分析

    一.线程池的介绍 线程池一种性能优化的重要手段.优化点在于创建线程和销毁线程会带来资源和时间上的消耗,而且线程池可以对线程进行管理,则可以减少这种损耗. 使用线程池的好处如下: 降低资源的消耗 提高响 ...

  5. Java核心复习 —— J.U.C 并发工具类

    一.CountDownLatch 文档描述 A synchronization aid that allows one or more threads to wait until* a set of ...

  6. Java核心复习——synchronized

    一.概念 利用锁机制实现线程同步,synchronized关键字的底层交由了JVM通过C++来实现 Java中的锁有两大特性: 互斥性 同一时间,只允许一个线程持有某个对象锁. 可见性 锁释放前,线程 ...

  7. Java核心复习——CompletableFuture

    介绍 JDK1.8引入CompletableFuture类. 使用方法 public class CompletableFutureTest { private static ExecutorServ ...

  8. Java核心复习—— ThreadLocal源码分析

    ThreadLocal,叫做线程本地存储,也可以叫做线程本地变量.ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量. 一.如何使用 class Acce ...

  9. Java核心复习——J.U.C LinkedBlockingQueue源码分析

    参考文档 LinkedBlockingQueue和ArrayBlockingQueue的异同

随机推荐

  1. 【转载】 Asp.Net安全之防止脚本入

    在ASP.NET开发过程中,安全性是必须要重中之重需要考虑的,其中一种情况是要防止用户输入恶意脚本入侵的情况,恶意脚本入侵指的是用户在提交内容中提交了包含特殊Javascript脚本程序等非法信息,如 ...

  2. SAP Marketing Cloud功能简述(三) 营销活动内容设计和产品推荐

    Grace的前两篇文章: SAP Marketing Cloud功能简述(一) : Contacts和Profiles SAP Marketing Cloud功能简述(二) : Target Grou ...

  3. c# 定制Equals()

  4. 解决windows 1903 alt + tab 切换卡顿

    右击此电脑图标 选择管理 服务和应用程序 服务 禁用system interface foundation service

  5. 使用Ponysay,在Linux终端显示彩虹小马

    Ponysay类似于Cowsay,可以在终端打印所有小马的像素画.还有个ponythink,这个是小马想,那个是小马说,效果如下: 安装: sudo apt-get install ponysay 使 ...

  6. cookie和session基础知识学习

    一.session的简单使用 session是服务器端技术,服务器在运行时可以为每一个用户的浏览器创建一个独享的session对象.session的使用步骤: 获取session对象使用session ...

  7. vue+webpack4 脚手架搭建

    1, vue 中 h => h(App) 的含义: //render: h => h(App) 是下面内容的缩写: render: function (createElement) { r ...

  8. NodeJS开发博客(三) 数据的保存

    什么是cookie 存储在浏览器的一段字符串(最大5k) 跨域不共享 格式如 k1=v1 k2=v2 因此可以存储结构化数据 每次发送http请求,会将请求域的cookie一起发送给server se ...

  9. css全局定位内容图片自动居中

    最近在做一个资讯站点时候,因为采集的数据,图片不居中,导致界面很不美观,所以需要全局定义下图片输出时候进行居中. .content img { max-width:800px;_width:expre ...

  10. virtual box启动error

      启动 VirtualBox 的时候提示 “获取 VirtualBox COM 对象失败” 错误详情 “获取 VirtualBox COM 对象失败” 的错误详情: 获取 VirtualBox CO ...