Java并发编程的艺术(二)——Java内存模型

Java内存模型

软件和硬件的共同目标是在不改变程序执行结果的前提下尽可能提高并行度,从而提高运行的效率(在准确的前提下越快越好)

多线程情况下如何不改变程序执行结果会引发如下的思考:

问题:

  1. 线程之间如何通信
  2. 线程之间如何同步

JVM内存中的方法区以及Java堆是线程共享的区域,在程序运行过程中不断的有线程修改共享区域中的变量值,那么如何确保多线程情况下程序运行的结果依旧是正确的?

首先我们需要了解一些基础的方法论,看看工程师们如何建立稳固的内存模型来支持多线程的正确运行

要想多线程运行准确,需要确保程序运行的顺序是正确的,共享的资源也需要按照一定的顺序进行读写。归根结底就是对于代码运行顺序的控制与理解。

但是工程师们太贪了,为了优化真的是不择手段。有人理直气壮的说只要能保证咱们的程序最终的执行结果一样,为什么不在编译器和处理器里对指令进行重新的排序从而使得指令可以并行运行进而提高效率呢?(典型的所谓只看结果不看过程的理工男)

我不管你中间经历了什么,我只要你给我一个正确的结果!!!

于是重排序就诞生了。

1.重排序

重排序:编译器和处理器对于执行顺序的优化,在不影响最终执行结果的前提下对指令进行重新组织排序

重排序确实能带来一定的优化,主要还是集中在单线程情况下的优化,但是在多线程情况下,随之而来的就是线程安全问题。比如线程A中的指令可能会用到线程B中的结果,那么A中的重排序将会影响到程序是否能正常运行。

为了解决这个问题,工程师们又提出了许多内存模型,通过制定相应的规则来限制编译器和处理器的重排序操作,确保程序按照正确的语序进行执行。

内存模型基本概念
下图是JMM内存模型示意图
-本地内存(虚拟出来的内存,线程自己拥有的)
-主内存(线程共享的)
JMM内存模型示意图

如何确保内存读取和程序运行的顺序一致?通过增加一些规范,又称语义

2. Java内存模型中的顺序一致性

happens-before
JMM中如果一个操作的执行结果需要对另外一个操作可见,那么这两个操作存在happens-before的关系
误区:并不是前一个操作要在后一个操作之前完成,重点是执行结果的顺序

as-if-serial
编译器和处理器不会对于具有数据依赖的程序进行重排序,因为该重排序会改变程序的运行结果

顺序一致性内存模型
I.一个线程中的所有操作都必须按照程序的顺序来执行
II.所有线程都只能看到单一的操作执行顺序,每个操作必须原子执行并且立刻对所有线程可见

区别:在JMM中,获取锁和释放锁之间的临界区代码可能存在重排序操作,而顺序一致性内存模型则是严格遵守执行顺序。

多线程领域的正确读写问题一直是工程师们头疼的地方,既然要使用多线程提高效率,必然会增加编程的复杂度,对存储的控制也提高到了一个新的台阶,但是为了性能,为了人类进步的大业,掉点头发不算什么:)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值