首先Java内存模型不是“JVM 的内存模型”;
Java线程之间的通信采用的是共享内存模型,这里提到的共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入何时对另一个线程可见。
从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,线程被CPU执行,每个线程都有一个私有的本地内存(如CPU的高速缓存),本地内存中存储了该线程以读/写共享变量的副本。
(重点)本地内存是JMM的一个抽象概念,并不真实存在;它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。
Java 内存模型规定所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(比如CPU的高速缓存)。
线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作,并且每个线程不能访问其他线程的工作内存。
(重点)那为什么Java的内存模型规范要这样定义导致出现线程本地内存和主存的值不同步呢?为啥线程要有自己的本地内存?
答案是利用缓存和改变执行代码顺序达到程序执行效率优化。
例如下面代码:
int a1 = x; int a2 = y; int a3 = x;
可能会被转化为:
int a2 = y; int a1 = x; int a3 = x;
或者是:
int a1 = x; int a2 = y; int a3 = a1;
这样和最初的代码相比,少读x一次。
Java 内 存 模 型 的 Volatile 关 键 字 和 原 子 性 、 可 见 性 、 有 序 性 和 happens-before 关系等。
一.Volatile 关键字 https://www.cnblogs.com/theRhyme/p/9396834.html
二.要想并发程序正确地执行,必须要保证原子性、可见性以及有序性。 只要有一个没有被保证,就有可能会导致程序运行不正确。
happens-before 原则(先行发生原则,有序性):
程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在 后面的操作
锁定规则:一个 unLock 操作先行发生于后面对同一个锁的 lock 操作
volatile 变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
传递规则:如果操作 A 先行发生于操作 B,而操作 B 又先行发生于操作 C,则可以 得出操作 A 先行发生于操作 C
线程启动规则:Thread 对象的 start()方法先行发生于此线程的每个一个动作
线程中断规则:对线程 interrupt()方法的调用先行发生于被中断线程的代码检测 到中断事件的发生
线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过 Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
对象终结规则:一个对象的初始化完成先行发生于他的 finalize()方法的开始。
硬件内存架构:https://www.cnblogs.com/theRhyme/p/9600148.html
Java内存模型——oracle官网文档: https://docs.oracle.com/javase/specs/jls/se9/html/jls-17.html#jls-17.4
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2018-06-04 Java可重入锁与不可重入锁