Java内存模型以及之前规则

  


https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q

1。JMM的介绍


在上一篇文章中总结了虽然这种回答似乎不能获取什么内容,可以谷歌下。在& lt; & lt;深入理解Java虚拟机在祝辞中看到的定义。原文如下:当多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替运行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获取正确的结果,那这个对象是线程安全的。


关于定义的理解这是一个仁者见仁智者见智的事情。出现线程安全的问题一般是因为和导致的,而解决线程安全的问题最重要的就是理解这两种问题是怎么来的,那么,理解它们的核心在于理解Java内存模型(JMM)。


在多线程条件下,多个线程肯定会相互协作完成一件事情,一般来说就会涉及到等,另外,为了性能优化,还会。下面会一一来聊聊这些知识。


2。内存模型抽象结构


线程间协作通信可以类比人与人之间的协作的方式,在现实生活中,之前网上有个流行语“你妈喊你回家吃饭了”,就以这个生活场景为例,小。明在外面玩耍,小。明妈妈在家里做的饭,做晚饭后准备叫小。明回家吃的饭,那么就存在两种方式:


小。明妈妈要去上班了十分紧急这个时候手机又没有电了,于是就在桌子上贴了一张纸条“饭做好了,放在……”小。明回家后看到纸条如愿吃到妈妈做的饭菜,那么,如果将小。明妈妈和小。明作为两个线程,那么这张纸条就是这两个线程间通信的共享变量,通过读写共享变量实现两个线程间协作;


还有一种方式就是,妈,妈。的手机还有电,妈妈在赶去坐公交的路上给小。明打了个电话,这种方式就是通知机制来完成协作。同样,可以引申到线程间通信机制。


通过上面这个例子,应该有些认识。在并发编程中主要需要解决两个问题:(这里的线程指的是并发执行的活动实体)。通信是指线程之间以何种机制来交换信息,主要有两种:共享内存和消息传递。这里,可以分别类比上面的两个举例。

java内存模型是,线程之间主要通过读-写共享变量来完成隐式通信。如果程序员不能理解java的共享内存模型在编写并发程序时一定会遇到各种各样关于内存可见性的问题。




在java程序中所有都是放在堆内存中(所有线程均可访问的到,是可以共享的),而局部变量,方法定义参数和异常处理器参数不会在线程间共享。共享数据会出现线程安全的问题,而非共享数据不会出现线程安全的问题。关于JVM运行时内存区域在后面的文章会讲到。




我们知道CPU的处理速度和主存的读写速度不是一个量级的,为了平衡这种巨大的差距,每个CPU都会有缓存。因此,共享变量会先放在主存中,每个线程都有属于自己的工作内存,并且会把位于主存中的共享变量拷贝到自己的工作内存,之后的读写操作均使用位于工作内存的变量副本,并在某个时刻将工作内存的变量副本写回到主存中去.JMM就从抽象层次定义了这种方式,并且JMM决定了一个线程对共享变量的写入何时对其他线程是可见的。

癹ava内存模型以及之前规则“


如图为JMM抽象示意图,线程和一线程B之间要完成通信的话,要经历如下两步:

<李>

线程一个从主内存中将共享变量读入线程一个的工作内存后并进行操作,之后将数据重新写回到主内存中,

<李>

线程B从主存中读取最新的共享变量

从横向去看看,线程和一线程B就好像通过共享变量在进行隐式通信。这其中有很有意思的问题,如果线程一个更新后数据并没有及时写回到主存,而此时线程B读到的是过期的数据,这就出现了“脏读“现象。可以通过同步机制(控制不同线程间操作发生的相对顺序)来解决或者通过动荡的关键字使得每次波动变量都能够强制刷新到主存,从而对每个线程都是可见的。


3。重排序


一个好的内存模型实际上会放松对处理器和编译器规则的束缚,也就是说软件技术和硬件技术都为同一个目标而进行奋斗:在不改变程序执行结果的前提下,尽可能提高并行度.JMM对底层尽量减少约束,使其能够发挥自身优势,因此,在执行程序时,,一般重排序可以分为如下三种:

Java内存模型以及之前规则