当前位置: 首页 > news >正文

java内存模型:

一、概念:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的副本。
例如:一个局部变量如果是原始类型,那么它会被完全存储到栈区。 
一个局部变量也有可能是一个对象的引用,这种情况下,这个本地引用会被存储到栈中,但是对象本身仍然存储在堆区。
对于一个对象的成员方法,这些方法中包含局部变量,仍需要存储在栈区,即使它们所属的对象在堆区。 
对于一个对象的成员变量,不管它是原始类型还是包装类型,都会被存储到堆区。Static类型的变量以及类本身相关信息都会随着类本身存储在堆区。

  八大基本类型:原始类型(boolean,byte,short,char,int,long,float,double)
二、八大原子操作:
1.lock:作用于主内存的变量,把一个变量标记为一条线程独占状态
2.unlock:把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定
3.read(读取):作用于主内存中,需要先对变量进行副本的拷贝,然后将变量值传输到工作内存中
4.load(载入):在工作内存中,需要对传输过来的副本变量进行一个获取,并且存入到工作内存中
5.use(使用): 需要将获取的变量传给执行引擎
6.assign(赋值):执行引擎会将这个收到的变量赋值给工作内存的变量
7.store(存储):修改这个传过来的副本之后,会将修改的值存储并送到主内存中
8.write(写入):会将这个存储的变量写回到主内存中,即修改主内存的值
同时在使用这八种原子操作时,需要满足以下的规则:
1.如果要把一个变量从主内存中复制到工作内存,就需要按顺寻地执行read和load操作, 如果把变量从工作内存中同步回主内存中,就要按顺序地执行store和write操作。但Java内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行。
2.不允许read和load、store和write操作之一单独出现
3.不允许一个线程丢弃它的最近assign的操作,即变量在工作内存中改变了之后必须同步到主内存中。
4.不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步回主内存中。
5.一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量。即就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。
6.一个变量在同一时刻只允许一条线程对其进行lock操作,但lock操作可以被同一条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。lock和unlock必须成对出现
7.如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值
8.如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。
9.对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。

三、重排序类型:
1.编译器优化的重排序。
2.指令集重排序
3.内存系统的重排序
四、as-if-serial:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变    
五、Happens-Before: happens-before关系保证正确同步的多线程程序的执行结果不被改变。
原则:
1.程序顺序原则:即在一个线程内必须保证语义串行性,也就是说按照代码顺序执行。
2.锁规则:解锁(unlock)操作必然发生在后续的同一个锁的加锁(lock)之前,也就是说,如果对于一个锁解锁后,再加锁,那么加锁的动作必须在解锁动作之后(同一个锁)。
3.volatile规则: volatile变量的写,先发生于读,这保证了volatile变量的可见性,简单的理解就是,volatile变量在每次被线程访问时,都强迫从主内存中读该变量的值,而当该变量发生变化时,又会强迫将最新的值刷新到主内存,任何时刻,不同的线程总是能够看到 该变量的最新值。
4.线程启动规则:线程的start()方法先于它的每一个动作,即如果线程A在执行线程B的start方法之前修改了共享变量的值,那么当线程B执行start方法时,线程A对共享变量的修改对线程B可见
5.传递性:A先于B ,B先于C 那么A必然先于C
6.线程终止规则:线程的所有操作先于线程的终结,Thread.join()方法的作用是等待当前执行的线程终止。假设在线程B终止之前,修改了共享变量,线程A从线程B的join方法成功返回后,线程B对共享变量的修改将对线程A可见。
7.线程中断规则:对线程 interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测线程是否中断。
8.对象终结规则:对象的构造函数执行,结束先于finalize()方法
六、内存语义:可以简单理解为 volatile,synchronize,atomic,lock 之类的在 JVM 中的内存方面实现原则
七、保存可见性:
1.内存屏障,
2.上下文切换
八、cpu缓存架构:寄存器,程序计数器,高速缓存,逻辑运算单元组成    
高速缓存:一级缓存2个(一个存储数据、一个存储指令)、二级缓存、三级缓存
九、解决这种缓存一致性的问题,主要有两种解决方式:嗅探机制、基于目录的机制
1.嗅探机制:就是说如果存在多个缓存被共享的时候,如果有处理器修改了共享变量的值,那么必须传播到其他所有具有该变量的副本中,通过这种传播机制来防止系统违反缓存的一致性。就是说,数据的变更通知是通过总线来完成的。
2.写失效:就是某个处理器将值改完之后,直接通知其他处理器,让其他处理器的缓存值失效  
3.写更新:就是处理器将值修改完之后,在通知其他处理器的时候,直接将值携带上,让其他的处理器缓存值更新
4.MSI、MESI、MOSI、MOESI等是最常见的缓存一致性协议
十、解决缓存一致性的MESI
1.为了解决缓存一致性,使用最多的方式是这种MESI的方式,总共有四种状态,分别是
M:modify,修改状态
E:Exclusive,独占状态
S:Share,共享状态
I:Invalid,失效状态


十一、内存屏障:
LoadStore:在store2指令写入数据之前,保证数据一定被load1指令先写入进去
LoadLoad:在Load2指令读取数据之前,保证数据一定被load1指令先读取出来
StoreLoad:在Load2指令读取数据之前,保证数据一定被Store指令写入进去
StoreStore:在store2指令写入数据之前,保证数据一定被load1指令读取出来


十二、单例模式:
public class SingletonTest{
private volatile static SingletonTest instance = null;
private SingletonTest() {}

    public static SingletonTest getInstance() {
if (instance == null) {
synchronized (SingletonTest.class) {
if (instance == null) {
//在不加volatile或者其他锁的情况下
//可能会出现指令重排的情况
instance = new Singleton();
}
}
}
return instance;
}
}

CAS自旋锁:
1.概念:cas比较和交换,通过jmm的java内存模型,借助于自旋的方式不断的去进行比较与交换,在每个对象的比较与交换中,主要是通过调用jvm的native本地方法去实现,从而去调用操作系统,在操作系统底层,cas借助了锁总线的串行方法来保证整个命令的原子操作,从而可以保证最终结果的一致性。
2.优点:相对于其他的重锁,cas底层采用的是无锁算法,通过#lock前缀指令达到内存屏障的效果,从而保证数据的可见性,一致性和有序性,其内部需要花费的时间,也远远小于其他的重锁,如synchronized等。
3.缺点:长时间的自旋耗费CPU资源;只能有一个共享变量的操作;ABA问题

http://www.dtcms.com/a/334886.html

相关文章:

  • Ubuntu 25.04更新了哪些内容揭秘
  • PHP反序列化的CTF题目环境和做题复现第1集
  • lesson40:PyMySQL完全指南:从基础到高级的Python MySQL交互
  • 【大语言模型 00】导读
  • 【Docker】Ubuntu上安装Docker(网络版)
  • 双指针和codetop复习
  • Hexo 双分支部署指南:从原理到 Netlify 实战
  • 【遥感图像技术系列】遥感图像风格迁移的研究进展一览
  • SymPy 矩阵到 NumPy 数组的全面转换指南
  • Redis 04 Reactor
  • eChart饼环pie中间显示总数_2个以上0值不挤掉
  • 【集合框架List进阶】
  • 【UHD】vivado 2021.1 编译
  • 选择式与生成式超启发算法总结
  • 模型训练监控:TensorBoard与Weights Biases (WB) 使用详解
  • CVE-2024-28752漏洞复现
  • 电子电气架构 --- 软件项目配置管理
  • 序列晋升7:架构原则三十诫
  • 内网穿透实战笔记 1panel 面板部署 frps,Windows 部署 frpc
  • 程序设计|C语言教学——C语言基础3:函数、数组、指针
  • Python虚拟环境与包管理工具(uv、Conda)
  • 一汽红旗7月销量37324辆 同比增长21.1%
  • B站 韩顺平 笔记 (Day 20)
  • P2169 正则表达式
  • 如何运用好DeepSeek为自己服务:智能增强的范式革命 1.1 认知增强的三次浪潮
  • 项目管理进阶——解读大型IT系统集成项目实施要点培训【附全文阅读】
  • GLM-4-Flash:智谱AI推出的首个免费API服务,支持128K上下文
  • 制作 Windows 11 启动U盘
  • Redis缓存
  • Win11和Win10共享打印机提示709用添加Windows凭据来解决的小方法