JMM(java内存模型)

JMM和JVM区别 

JMM和JVM还是有区别的,JMM主要作用于线程的共享变量定义,在变量CRUD之后其他的线程对该变量的可见性。JVM主要和java虚拟机的运行时环境有关,主要作用于定义存储数据的分区读写。

JMM变量共享方式

JMM中的变量共享主要依赖于主内存,在各个单独的线程拥有本地内存的情况下,线程的变量在发生变化之后首先缓存到本地,在通过副本共享到主内存,从而起到变量通信的作用。

JMM变量安全操作

JMM的变量共享方式决定了它在线程的数据安全性上需要有严格的把控,如果不做控制,必然会出现变量的数据错误,或者多线程协调的情况下,变量在不同线程中出现指令顺序造成的数据迟滞,从而导致主内存数据无法及时更新,线程变量不能实时通信。

针对上述问题,在JMM中通过八种操作做了变量的同步控制:

  • lock: 作用于主内存中的变量,标记该变量正处于线程使用阶段,当前状态先独属于一个线程,其他线程无权限做任何操作。
  • unlock: 作用于主内存中的变量,和lock操作配合使用,广播变量已经解锁,其他线程可以访问,在没有unlock情况下,变量会锁死直至unlock。
  • read:作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的 load 动作使用。
  • load:把 read 操作从主内存中得到的变量值放入工作内存的变量的副本中。
  • use:把工作内存中的一个变量的值传给执行引擎,每当虚拟机遇到一个使用到变量的指令时都会使用该指令。
  • assign:作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
  • store:作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的 write 操作使用。
  • write:作用于主内存的变量,它把 store 操作从工作内存中得到的变量的值放入主内存的变量中。

除了八种变量控制操作之外,还有一些同步规则需要了解,比如:

lock和unlock必须配套使用,也就是说使用了几次lock就必须用相同的unlock解锁,否则变量仍然处于锁死状态,其他线程依然无法访问。unlock操作不能解其他线程的lock(你解也没用,反正解不开...)

新的变量必须要在主内存中初始化加载,线程本地内存不能直接使用未在主内存生成的变量 。(用了也不生效,反正会报错...)

还有其他的坑慢慢踩吧。。。

JMM指令重排序

因为CPU和寄存器的存在,实际程序的执行顺序和编码可能并不一致,究其根本还是因为变量的存在造成的。指令重排序是为了提高程序的执行效率,毕竟happens-before原则也不是JVM自身处理的,相应的JIT也会指示编译成指令,让寄存器和CPU也遵守。

java中禁止指令重排的关键字只有volatile和final,这俩东西在某个层次上权限有点重叠,但是final使用时间需要好好考虑一下,毕竟有时间强制性约束会在多线程中造成问题。

我们知道,final修饰的是只读变量,有很强的“只读”约束性,所有final修饰的变量都需要在构造方法中初始化(类外部final字段的最终会插入到super(...)之后 ),而volatile一般用于多线程变量的读写,但他们都具备实现内存屏障的能力,可以说,都能实现禁止重排序。

不同点:

final字段的读写操作,读写取和volatile基本一样,但是没有可见性。

  • 27
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值