04-Java内存模型与线程

Java内存模型与线程

一、JMM定义

  • JMM是Java 虚拟机规范中定义的一种标准,其目的是为了屏蔽各种硬件和操作系统的差异(不同硬件平台的差异),让Java程序在各种平台下都能达到一致的访问效果;
定义JMM并不容易,一方面需要足够严谨而不产生歧义,其次也必须足够宽松让虚拟机的实现有足够的自由空间去利用硬件的
特性(寄存器、Cache以及不同平台特有的指令)

二、JMM细节

2.1 主存与工作内存

  • JMM规定线程对变量的操作都必须在线程的工作内存中进行,而不能直接读写主内存中的变量。不同线程之间也无法访问对方工作内存中的变量,线程之间的变量传递需要通过主内存来完成。

在这里插入图片描述

2.2 内存交互

  • JMM 规定了8种操作来完成变量在主存和工作内存之间的交互,按照读取到工作内存然后使用最后写会主存的顺序分别是:lock、read、load、use、assign、store、write、unlock
操作作用对象作用
lock主存变量锁定主存中的变量,标识为某线程占有状态
unlock主存变量解锁主存中的变量,解锁后其他线程才能占用
read主存变量读取主存中变量到线程工作内存
write主存变量将工作内存中变量值写入主存
load工作内存变量将read读取到工作内存中的变量值放入工作内存中的变量副本
use工作内存变量使用工作内存中的变量值
assign工作内存变量工作内存中变量赋值
store工作内存变量将工作内存中变量值传回主存

在这里插入图片描述

  • 注意图中的步骤JMM做了一些规定,比如read和load不允许出现一个,换言之要load必须先read,read后也不能没有load,write和store也一样,不过需要注意的是,read和load直接是可以插入其他指令的,read a 和load a中间可以有其他指令。另外比如lock的次数和unlock的次数要对应才能正确的释放,执行unlock的时候会将工作内存变量同步到主存,等;

2.3 volatile

  • 关于 volatile 变量,本文不深入开展,很多只是给出结论,其底层使用内存屏障指令来保证可见性和禁止指令重排序这两大特性,具体可以参考:16-Java多线程、volatile关键字

2.4 先行发生原则

  • 先行发生原则是JMM 中定义的两项操作之间的时序关系,A 先行发送于B,意味着B发生时,A所产生的影响都能被B感知到,比如对变量的修改,方法的调用以及其他操作,JMM定义了一系列规则来约束该原则;

  • 程序次序原则:一个线程内的控制流顺序中,前面的操作先行发生于后面的操作

  • 管程锁定原则:unLock操作先行发生于后面对同一个锁的lock操作;(这里的先后是指时间上的)

  • volatile变量原则:对volatile变量的写操作现行发生于对这个变量的读操作

  • 线程启动原则:线程Thread对象的start方法先行发生于线程的每一个动作

  • 线程终止原则:线程中的操作先行发生于对这个线程的终止检测,比如Thread.join()和Thread.isAlive()判断线程是否已经终止;

  • 传递性:A先行发生于B,B先行发生于C,那么A先行发生于C

Java与线程

  • Java中线程是模型是1:1,这里指的是每一个用户线程都对应一个内核线程,用户线程通过内核线程的高级接口实现,每个线程由内核操作调度器来实现调度,由此单个线程阻塞也不影响整个进程。但是这样带来了一些弊端:一方面线程的创建,销毁代价比较大,另一方面因为内核线程的数量受限,因此创建线程的数量也受到限制;

  • 线程的状态切换:

在这里插入图片描述

这里补充一下各种可能导致阻塞的情况:

  • Thread.sleep:释放Cpu,不释放锁
  • object.wait:等待锁
  • thread.join:底层是调用thread.wait,排队等待thread线程
  • LoclSupport.park():挂起线程
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值