java内存模型

Java内存模型的主要目标是定义程序中各个变量的访问规则,保证线程能够并发高效执行即在虚拟机中将变量存储到内存和从内存中取出变量这样底层细节。此处的变量与Java编程时所说的变量不一样,指包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,后者是线程私有的,不会被共享。

1.所有的变量都存储在主内存中
2.每个线程都还有自己的工作内存,拥有主内存的对象的拷贝
3.线程只能操作自己的工作内存,线程间的交互只能通过主内存通讯


java内存模型是围绕着在并发过程中如何处理原子性、可见性和有序性这三个特征来建立变量的访问规则的。
原子性,可见性和有序性
原子性:java内存模型直接保证6个变量操作(read、load、use、assign、store、write)都具有原子性(不可分割,在执行完毕之前是不可分割的),可以 认为基本数据类型的访问读写都是原子性(long和double除外)
可见性:可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。java内存模型是通过在变量修改后将新值 同步回主存,在变 量读取之前从主存刷新变量值这种依赖主内存作为传递媒介的方式来实现可见性的,无论是普通变量还是volatile变量都是如此,普通变量与 volatile变量的区别是,volatile的特殊规则能够保证新值立即同步到主存,以及每次使用时立即从主存刷新。其他两个关键字是synchronized final
有序性:如果在本线程内观察,所有的操作都是有序的;如果在一个线程中观察另一个线程,所有的操作都是无序的。前面是指“线程内表现为串行的 语义”,后面半句是指"指令重排"现象和"工作内存和主内存同步延时现象"。


内存间的交互操作
8种操作的作用场景,参考上面的图。
规则:
1.read 和load ,store和write 必须一对操作
2.不允许线程丢弃assign操作,变量在工作内存中改变后必须把变法同步回主内存
3.没有assign操作,不允许变量从工作内存同步回主内存
4.新变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化的变量(load或assign)
对一个变量实时use和store之前必须先执行过assign和load操作
5.一个变量同一时刻值允许一条线程lock操作,但lock操作可以多次,执行相同数量的unlock,变量才会解锁
6.lock操作会清空工作内存副本,执行引擎使用前,需要执行load或者assign操作初始化变量的值
7.没有lock操作,就不允许unlock操作。不允许unlock另一个线程变量。
8.unlock操作前必须先store,write操作

重排序

在执行程序时为了提高性能,编译器和处理器经常会对指令进行重排序。重排序分成三种类型:

  1. 编译器优化的重排序。编译器在不改变单线程程序语义放入前提下,可以重新安排语句的执行顺序。
  2. 指令级并行的重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
  3. 内存系统的重排序。由于处理器使用缓存和读写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
从Java源代码到最终实际执行的指令序列,会经过下面三种重排序:


为了保证内存的可见性,Java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序


volatile变量的特殊规则

一:保证此变量对所有线程的可见性,每次use之前都必须先read和load。

二:禁止指令重排序优化

volatile的变量附近的代码不会被指令重排序打乱。
具体是在变量操作之前代码不会被打乱到操作之后,操作之后的代码不会打乱到操作之前



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值