从 CPU 说起,深入理解 Java 内存模型

《深入理解JAVA内存模型》PDF 在java中,所有实例域、静态域和数组元素存储在堆内存中,堆内存在线程之间共享(本文使用“共享变量”这个术语代指实例域,静态域和数组元素)。局部变量(Local variables),方法定义参数(java语言规范称之为formal method parameters)和异常处理器参数(exception handler parameters)不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响。 Java线程之间的通信由Java内存模型(本文简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。 。。。。。。 立即下载

Java 内存模型,许多人会错误地理解成 JVM 的内存模型。但实际上,这两者是完全不同的东西。Java 内存模型定义了 Java 语言如何与内存进行交互,具体地说是 Java 语言运行时的变量,如何与我们的硬件内存进行交互的。而 JVM 内存模型,指的是 JVM 内存是如何划分的。

Java 内存模型是并发编程的基础,只有对 Java 内存模型理解较为透彻,我们才能避免一些错误地理解。Java 中一些高级的特性,也建立在 Java 内存模型的基础上,例如:volatile 关键字。

为了让大家能明白 Java 内存模型存在的意义,本篇文章将从计算机硬件出发,一路写到操作系统、编程语言,一环扣一环的引出 Java 内存模型存在的意义,让大家对 Java 内存模型有较为深刻的理解。看完之后,希望大家能够明白如下几个问题:

  • 为什么要有 Java 内存模型?
  • Java 内存模型解决了什么问题?
  • Java 内存模型是怎样的一个东西?

从 CPU 说起

我们知道计算机有 CPU 和内存两个东西,CPU 负责计算,内存负责存储数据,每次 CPU 计算前都需要从内存获取数据。我们知道 CPU 的运行速度远远快于内存的速度,因此会出现 CPU 等待内存读取数据的情况。

由于两者的速度差距实在太大,我们为了加快运行速度,于是计算机的设计者在 CPU 中加了一个 CPU 高速缓存。这个 CPU 高速缓存的速度介于 CPU 与内存之间,每次需要读取数据的时候,先从内存读取到 CPU 缓存中,CPU 再从 CPU 缓存中读取。这样虽然还是存在速度差异,但至少不像之前差距那么大了。

新增 CPU 高速缓存

随着技术的发展,多核 CPU 出现了,CPU 的计算能力进一步提高。原本同一时间只能运行一个任务,但现在可以同时运行多个任务。由于多核 CPU 的出现,虽然提高了 CPU 的处理速度,但也带来了新的问题:缓存一致性。

在多 CPU 系统中,每个处理器都有自己的高速缓存,而它们又共享同一主内存,如下图所示。当多个 CPU 的运算任务都涉及同一块主内存区域时,可能导致各自的缓存数据不一致。如果发生了这种情况,那同步回主内存时以哪个 CPU 高速缓存的数据为准呢?

多核 CPU 及高速缓存导致的问题

我们举个例子,线程 A 执行这样一段代码:

i = i + 10;

线程 B 执行这样一段代码:

i = i + 10;

他们的 i 都是存储在内存中共用的,初始值是 0。按照我们的设想,最终输出的值应该是 20 才对。但实际上有可能输出的值是 10。下面是可能发生的一种情况:

  • 线程 A 分配到 CPU0 执行,这时候读取 i 的值为 0,存到 CPU0 的高速缓存中。
  • 线程 B 分配到 CPU1 执行,这时候读取 i 的值为 0,存到 CPU1 的高速缓存中。
  • CPU0 进行运算,得出结果 10,运算结束,写回内存,此时内存 i 的值为 10。
  • CPU1 进行运算,得出结果 10,运算结束,写回内存,此时内存 i 的值为 10。

可以看到发生错误结果的主要原因是:两个 CPU 高速缓存中的数据是相互独立,它们无法感知到对方的变化。

到这里,就产生了第一个问题:硬件层面上,由于多 CPU 的存在,以及加入 CPU 高速缓存,导致的数据一致性问题。

要注意的是,这个问题是硬件层面上的问题。只要使用了多 CPU 并且 CPU 有高速缓存,那就会遇到这个问题。对于生产该 CPU 的厂商,就需要去解决这个问题,这与具体操作系统无关,也与编程语言无关。

那么如何解决这个问题呢?答案是:缓存一致性协议。

加入缓存一致性协议

所谓的缓存一致性协议,指的是在 CPU 高速缓存与主内存交互的时候,遵守特定的规则,这样就可以避免数据一致性问题了。

在不同的 CPU 中,会使用不同的缓存一致性协议。例如 MESI 协议用于奔腾系列的 CPU 中,而 MOSEI 协议则用于 AMD 系列 CPU 中,Intel 的 core i7 处理器使用 MESIF 协议。在这里我们介绍最为常见的一种:MESI 数据一致性协议。

在 MESI 协议中,每个缓存可能有有 4 个状态,它们分别是:

  • M (Modified):这行数据有效,数据被修改了,和内存中的数据不一致,数据只存在于本 Cache 中。
  • E (Exclusive):这行数据有效,数据和内存中的数据一致,数据只存在于本 Cache 中。
  • S (Shared):这行数据有效,数据和内存中的数据一致,数据存在于很多 Cache 中。
  • I (Invalid):这行数据无效。

那么在 MESI 协议的作用下,我们上面的线程执行过程就变为:

  • 线程 A 分配到 CPU0 执行,这时候读取 i 的值为 0,存到 CPU0 的高速缓存中。
  • 线程 B 分配到 CPU1 执行,这时候读取 i 的值为 0,存到 CPU1 的高速缓存中。
  • CPU0 进行运算,得出结果 10,运算结束,写回内存,此时内存 i 的值为 10。同时通过消息的方式告诉其他持有 i 变量的 CPU 缓存,将这个缓存的状态值为 Invalid。
  • CPU1 进行运算,从 CPU 缓存取出值,但是发现这个缓存值被置为 Invalid 了。于是重新去内存中读取,读取到 10 这个值放入 CPU 缓存。
  • CPU1 进行运算,得出结果 20,运算结束,写回内存,此时内存 i 的值为 20。

从上面的例子,我们可以知道 MESI 缓存一致性协议,本质上是定义了一些内存状态,然后通过消息的方式通知其他 CPU 高速缓存,从而解决了数据一致性的问题。

从操作系统说起

操作系统,它屏蔽了底层硬件的操作细节,将各种硬件资源虚拟化,方便我们进行上层软件的开发。在我们开发应用软件的时候,我们不需要直接与硬件进行交互,只需要和操作系统交互即可。

既然如此,那么操作系统就需要将硬件进行封装,然后抽象出一些概念,方便上层应用使用。于是 CPU 时间片、内核态、用户态等概念也诞生了。

前面我们说到 CPU 与内存之间会存在缓存一致性问题,那操作系统抽象出来的 CPU 与内存也会面临这样的问题。因此,操作系统层面也需要去解决同样的问题。所以,对于任何一个系统来说,它们都需要去解决这样一个问题。

我们把在特定的操作协议下,对特定内存或高速缓存进行读写访问的过程进行抽象,得到的就是内存模型了。 无论是 Windows 系统,还是 Linux 系统,它们都有特定的内存模型。

Java 语言是建立在操作系统上层的高级语言,它只能与操作系统进行交互,而不与硬件进行交互。与操作系统相对于硬件类似,操作系统需要抽象出内存模型,那么 Java 语言也需要抽象出相对于操作系统的内存模型。

一般来说,编程语言也可以直接复用操作系统层面的内存模型,例如:C++ 语言就是这么做的。但由于不同操作系统的内存模型不同,有可能导致程序在一套平台上并发完全正常,而在另外一套平台上并发访问却经常出错。因此在某些场景下,就必须针对不同的平台来编写程序。

而我们都知道 Java 的最大特点是「Write Once, Run Anywhere」,即一次编译哪里都可以运行。而为了达到这样一个目标,Java 语言就必须在各个操作系统的基础上进一步抽象,建立起一套对内存或高速缓存的读写访问抽象标准。这样就可以保证无论在哪个操作系统,只要遵循了这个规范,都能保证并发访问是正常的。

Java 内存模型 - 不同层面抽象及方案

Java 内存模型

经过了前面的铺垫,相信你已经明白了为什么要有 Java 内存模型,以及 Java 内存模型是什么,有了一个感性的理解。这里我们再给 Java 内存模型下一个较为准确的定义。

Java 内存模型(Java Memory Model,JMM)用于屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台都能达到一致的内存访问效果。

Java 内存模型定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。

这里说的变量包括了实例字段、静态字段和构成数组对象的元素,但不包括局部变量与方法参数。因为后者是线程私有的,不会被共享,自然就不会存在竞争问题。

内存模型的定义

Java 内存模型规定所有的变量都存储在主内存中,每条线程都有自己的工作内存。线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量。

不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递都需要通过主内存来完成。主内存、工作内存、线程三者之间的关系如下图所示。

Java 内存模型图解

Java 内存模型的主内存、工作内存与 JVM 的堆、栈、方法区,并不是同一层次的内存划分,两者是没有关联的。如果一定要对应一下,那么主内存主要对应于 Java 堆中对象实例的数据部分,而工作内存则对应于虚拟机栈中的部分区域。

内存间的交互

关于主内存与工作内存之间具体的交互协议,即一个变量如何从主内存拷贝到工作内存,以及如何从工作内存同步回主内存的细节,Java 内存模型定义了 8 种操作来完成。虚拟机实现的时候必须保证下面提及的每一种操作都是原子的、不可再分的。

  • lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。
  • unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
  • read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的 load 动作使用。
  • load(载入):作用于工作内存的变量,它把 read 操作从主内存中得到的变量值放入工作内存的变量副本中。
  • use(使用):作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作。
  • assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
  • store(存储):作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的 write 操作使用。
  • write(写入):作用于主内存的变量,它把 store 操作从工作内存中得到的变量的值放入主内存的变量中。

如果要把一个变量从主内存复制到工作内存,那就要顺序地执行 read 和 load 操作,如果要把变量从工作内存同步回主内存,就要顺序地执行 store 和 write 操作。注意,Java 内存模型只要求上述两个操作必须按顺序执行,而没有保证是连续执行。也就是说,read 与 load 之间、store 与 write 之间是可插入其他指令的,如对主内存中的变量 a、b 进行访问时,一种可能出现顺序是 read a、read b、load b、load a。

此外,Java 内存模型还规定上述 8 种基本操作时必须满足如下规则:

  • 不允许 read 和 load、store 和 write 操作之一单独出现,即不允许一个变量从主内存读取了但工作内存不接受,或者从工作内存发起回写了但主内存不接受的情况出现。
  • 不允许一个线程丢弃它的最近的 assign 操作,即变量在工作内存中改变了之后必须把该变化同步回主内存。
  • 不允许一个线程无原因地(没有发生过任何 assign 操作)把数据从线程的工作内存同步回主内存中。
  • 一个新的变量只能在主内存中「诞生」,不允许在工作内存中直接使用一个未被初始化(load 或 assign)的变量,换句话说,就是对一个变量实施 use、store 操作之前,必须先执行过了 assign 和 load 操作。
  • 一个变量在同一个时刻只允许一条线程对其进行 lock 操作,但 lock 操作可以被同一条线程重复执行多次,多次执行 lock 后,只有执行相同次数的 unlock 操作,变量才会被解锁。
  • 如果对一个变量执行 lock 操作,那将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行 load 或 assign 操作初始化变量的值。
  • 如果一个变量事先没有被 lock 操作锁定,那就不允许对它执行 unlock 操作,也不允许去 unlock 一个被其他线程锁定住的变量。
  • 对一个变量执行 unlock 操作之前,必须先把此变量同步回主内存中(执行 store、write 操作)。

这 8 种内存访问操作以及上述规则限定,再加上稍后介绍的对 volatile 的一些特殊规定,就已经完全确定了 Java 程序中哪些内存访问操作在并发下是安全的。

总结

这篇文章我们从底层 CPU 开始讲起,一直讲到操作系统,最后讲到了编程语言层面,让大家能够一环扣一环地理解,最后明白 Java 内存模型诞生的原因(上层有数据一致性问题),以及最终要解决的问题(缓存一致性问题)。

看到这里,我们大概把为什么要有 Java 内存模型讲清楚了,也知道了 Java 内存模型是什么。最后我们来做个总结:

由于多核 CPU 和高速缓存在存在,导致了缓存一致性问题。这个问题属于硬件层面上的问题,而解决办法是各种缓存一致性协议。不同 CPU 采用的协议不同,MESI 是最经典的一个缓存一致性协议。

操作系统作为对底层硬件的抽象,自然也需要解决 CPU 高速缓存与内存之间的缓存一致性问题。各个操作系统都对 CPU 高速缓存与缓存的读写访问过程进行抽象,最终得到的一个东西就是「内存模型」。

Java 语言作为运行在操作系统层面的高级语言,为了解决多平台运行的问题,在操作系统基础上进一步抽象,得到了 Java 语言层面上的内存模型。

Java 内存模型分为工作内存与主内存,每个线程都有自己的工作内存。每个线程都不能直接与主内存交互,只能与工作内存交互。此外,为了保证并发编程下的数据准确性,Java 内存模型还定义了 8 个基本的原子操作,以及 8 条基本的规则。

如果 Java 程序能够遵守 Java 内存模型的规则,那么其写出的程序就是并发安全的,这就是 Java 内存模型最大的价值。

深入理解 Java 内存模型

Mplus实战:随机截距交叉滞后模型(RI-CLPM)在心理学纵向研究中的进阶应用 本文深入探讨了随机截距交叉滞后模型(RI-CLPM)在心理学纵向研究中的进阶应用,通过Mplus实战演示了模型设定、结果解读及进阶建模策略。RI-CLPM能有效区分个体间差异和个体内变化,适用于追踪青少年手机使用与抑郁症状等研究。文章还提供了样本量规划、模型比较和结果可视化等实用技巧,助力研究者避免常见陷阱。 阅读详情

相关推荐

极验第四代滑块验证码破解(三):滑块轨迹构造

极验第四代滑块验证码破解(三):滑块轨迹构造声明 声明 原创文章,请勿转载! 本文内容仅限于安全研究,不公开具体源码。维护网络安全,人人有责。 本文关联文章超链接:

帯泪的鱼的博客 8624

Java内存模型

Java内存模型

RogerLuoji的博客 777

深入理解Java内存模型

多任务处理在现代计算机系统中几乎是一项必备的功能了,让计算机同时去做多个事情,并不是因为计算机的处理能力强大,而是因为计算机的运算速度和子系统的速度差距很大,如果计算机不去同时处理多任务,大量的时间都浪费在了磁盘IO上,网络通信和数据库访问上,而在等待磁盘IO等耗时操作时计算机却不能做其他事情,所以我们要去“压榨”计算机的运算能力,为了让计算机同时做多件事情,就有了多线程。...

weixin_46017166的博客 591

数字麦克风PDM信号采集与STM32 I2S接口应用(二)

在使用STM32的数字麦克风I2S接口时,计算采样率让人头疼,芯片手册上没有明确的说法,而手册上的计算方法经过测试却和实验不符。借助搜索引擎,大部分资料都是来自于开发板卖家或开发板论坛,主要是咪头采集然后配置WM89系列解码芯片,然后配合FatFS、MP3解码等模式,主要是讲解I2S录音、存储、放音等。外文资料得到的也寥寥无几,也没有找到讲解STM32数字麦克风配置、计算的文档。加上网上资料转载、抄袭、浅尝辄止的笔记教程,这些更是让检索大海捞针,过程艰辛一言难尽,有些网文三言两语抑或作者都没有搞清楚随手一写

XIAOYOUDUODUO的博客 6057

从OSGB到3DTiles:倾斜摄影数据高效转换实战指南

本文提供了将倾斜摄影OSGB数据高效转换为Web友好的3DTiles格式的完整实战指南。详细介绍了使用开源工具进行转换的步骤,包括环境搭建、核心命令、参数调优及在Cesium中加载与问题排查,旨在帮助GIS开发者和三维应用工程师打通数据到Web展示的最后一公里,实现大规模三维模型的流畅网络发布。

u0v1w2x3的博客 570

关于Java内存模型的理解

由于不同CPU架构的缓存体系、缓存一致性协议、重排序策略不一样,提供的内存屏障指令也有差异,所以为了简化Java开发工作,Java封装了一套规范,也就是Java内存模型。 Java内存模型希望屏蔽各种硬件和操作系统的访问差异,保证了Java程序在各种平台下对内存的访问都能得到一致效果,目的是解决多线程存在的原子性、可见性和有序性问题。

BAStriver的博客 832

链路聚合Eth-trunk以及华为交换机配置实例

链路聚合简介 以太网链路聚合Eth-Trunk简称链路聚合,它通过将多条以太网物理链路捆绑在一起成为一条逻辑链路,从而实现增加链路带宽的目的。同时,这些捆绑在一起的链路通过相互间的动态备份,可以有效地提高链路的可靠性。 目的: 随着网络规模不断扩大,用户对骨干链路的带宽和可靠性提出越来越高的要求。在传统技术中,常用更换高速率的接口板或更换支持高速率接口板的设备的方式来增加带宽,但这种方案需要付出高额的费用,而且不够灵活。 采用链路聚合技术可以在不进行硬件升级的条件下,通过将多个物理接口捆绑为一个逻辑接口

ChaseAug的博客 2万+

Java线上服务CPU、内存飙升问题排查步骤!

如果是Full GC次数过多,那么通过 jstack得到的线程信息会是类似于VM Thread之类的线程,而如果是代码中有比较耗时的计算,那么我们得到的就是一个线程的具体堆栈信息。下面将总结一些具体的排查步骤。首先找到该接口,通过压测工具不断加大访问力度,如果说该接口中有某个位置是比较耗时的,由于我们的访问的频率非常高,那么大多数的线程最终都将阻塞于该阻塞点。这是比较麻烦的一种情况,因为一般来说,其消耗的CPU不多,而且占用的内存也不高,也就是说,我们通过上述两种方式进行排查是无法解决这种问题的。

伤心的辣条 9645

Cadence 中Cutout、Design_Outline 和 Outline的区别

摘要: 在PCB设计中,Cutout、Design_Outline和Outline都与电路板外形相关但用途不同。Cutout用于定义切割区域(如孔、槽),直接影响制造;Design_Outline仅标记设计边界,作为参考不影响切割;Outline则是实际切割轮廓层,用于制造。三者区别在于:Cutout针对具体切割区域,Design_Outline是设计参考,Outline是最终切割依据。设计时需根据需求选择合适层:外形参考用Design_Outline/Outline,切割区域用Cutout。

卤煮小鱼的博客 1802

23、关联挖掘到相关性分析及约束关联挖掘详解

本文详细解析了从关联挖掘到相关性分析的发展过程,以及基于约束的关联挖掘方法。文章介绍了传统支持-置信度框架的局限性,并引入Lift、χ2、All Confidence和Cosine等度量来评估规则的相关性。同时探讨了多种规则约束在数据挖掘中的应用机制及其优化效果,旨在提高挖掘效率和规则质量。最后结合实际案例说明如何综合运用相关性度量与规则约束以满足业务需求,并展望了数据挖掘技术的未来发展。

aa123的博客 103

从 CPU 说起,深入理解 Java 内存模型!

Java 内存模型,许多人会错误地理解成 JVM 的内存模型。但实际上,这两者是完全不同的东西。Java 内存模型定义了 Java 语言如何与内存进行交互,具体地说是 Java 语言运行时的变量,如何与我们的硬件内存进行交互的。而 JVM 内存模型,指的是 JVM 内存是如何划分的。Java 内存模型是并发编程的基础,只有对 Java 内存模型理解较为透彻,我们才能避免一...

陈树义 176

手把手教你学Simulink实例--基于simulink搭建起一个基础的矩阵变换器仿真模型

矩阵变换器(Matrix Converter, MC)是一种直接将交流电源转换为另一频率和幅值的交流电源的电力电子设备,它不需要中间的直流环节。这种变换器通过控制一组双向开关来实现对输入电压的精确控制,从而产生所需的输出电压波形。Simulink提供了强大的仿真环境,可以用于设计、分析和验证基于矩阵变换器的电源系统。

MHD0815的博客 340

深入理解Java内存模型及其作用

当问到 Java 内存模型的时候,一定要注意,Java 内存模型(Java Memory Model,JMM)它和 JVM 内存布局(JVM 运行时数据区域)是不一样的,它们是两个完全不同的概念。Java 内存模型(Java Memory Model,简称 JMM)是一种规范,它定义了 Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式,即规范了 Java 虚拟机与计算机内存之间是如何协同工作的。

qq_35716689的博客 1万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

从 CPU 讲起,深入理解 Java 内存模型

Java 内存模型,许多人会错误地理解成 JVM 的内存模型。但实际上,这两者是完全不同的东西。Java 内存模型定义了 Java 语言如何与内存进行交互,具体地说是 Java 语言运行时的变量,如何与我们的硬件内存进行交互的。而 JVM 内存模型,指的是 JVM 内存是如何划分的。Java 内存模型是并发编程的基础,只有对 Java 内存模型理解较为透彻,我们才能避免一些错误地理解。Java 中一些高级的特性,也建立在 Java 内存模型的基础上,例如:volatile 关键字。为了让大家能明白 Java

weixin_70886371的博客 155

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

线程安全-从CPU讲起,深入理解 Java 内存模型

线程安全-从CPU讲起,深入理解Java内存模型

LuckyRascal的博客 266

原创 | 深入理解Java内存模型(上)!

Java内存模型是学习Java虚拟机中必须要会的一个知识点,而且是重点,经常有人把Java内存模型和Java内存结构混为一谈。 以后别乱点鸳鸯篇了,这俩货真的不是一个品种! 今天我们就一起来看看到底Java内存模型是个啥,希望看完今天的文章,以后就不要再学Java内存模型,为啥不学了?因为已经会了啊! 首先,还是希望大家分清楚几个概念: 1.Java内存模型(今天的主角) 2.Java内存结构...

庆哥Java的优快云技术博客 2712

深入理解Java并发编程:从办公室场景说起

深入理解Java并发编程:从办公室场景说起

daweias的博客 1943

volatile的设计原理,得从硬件CPU说起

原文链接:https://mp.weixin.qq.com/s/WTqdSz-lc5zzelJgk4Co8g写volatile的文章非常多,本人也看过许多相关文章,但始终感觉有哪里不太明白,但又说不上来说为什么。可能是过于追求底层实现原理,老想问一个为什么吧。而写这篇文章的目的很简单,就是突然之间明白了volatile为什么要这样设计了。好东西当然要拿出来分享了,于是就有了这篇文章。我们就从硬件到软件,再到具体的案例来聊聊volatile的底层原理,文章比较长,可收藏之后阅读。CPU缓存的出现最初的CPU是

城北荆无命的博客 779

Java 内存模型,或许应该这么理解

大家好,我是树哥。在前面一段时间,我连续写了几篇关于并发编程的文章:从 CPU 说起,深入理解 Java 内存模型!深入理解 happens-before 原则深入理解 volatile 关键字深入理解 synchronized 的锁优化深入理解 Java 对象的内存布局这几篇文章分别讲了 Java 内存模型、happens-before 原则、volatile 关键字、...

陈树义 109
上一篇: Java -Version的秘密
下一篇: 架构师之路,从「存储选型」起步
JavaMonsterr
博客等级 码龄4年 211粉丝 481原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值