没怎么搞过java 不过看到这篇文章对自己有些理解有帮助 所以做了一个读书笔记
JMM java memory modal JAVA内存模型
重排序:前部分讲了几种层面的重排序会导致线程里面的顺序 并不会按照看到的顺序执行.
重排序的几种分类:编译器优化,cpu优化(这个可以联想到现在的超线程技术,就是允许多个线程的指令在同一块物理单元里执行,一个物理cpu被当做两个逻辑cpu)
还有就是内存系统的重排。这个可以联想一下c预言里有个关键字volatile .在多个线程同时对一个变量进行操作的时候他的通信模型是这样的。
我们可以看到,更新操作其实都是更新了缓存然后需要一个刷新到内存的动作,才能使内存保存一直。
各种cpu允许重排序的列表:
Java里面分为集中内存屏障 保证多线程读写时数据同步
关于java的happen-before模型:个人理解的意思就是禁用一些编译器重排序然后保证,其中的顺序性?
正确使用同步,JMM模型会保证线程一致性内存模型 (在使用 synchronized volatile final的时候)
具有竞争的线程 在同一时间内只能串行执行 读写同步的动作
加上snchronized关键字之后 临界区之内的线程内部代码可以重排序也可以顺序(JMM允许了重排序)
重排序之后的内容对于另一个线程是不可见的 所以不影响另一个线程(不允许临界区内的代码溢出到临界区外)
在不改变执行结果的前提下尽量满足编译器的优化政策
一致性内存模型与JMM相比的一些特点:
- 顺序一致性模型 会按照顺序执行但是不保证单线程内的指令会按照顺序执行(这样做的好处是效率高不损失编译器的优化)。
- 多个线程一块执行时是否保证一致的执行顺序看下面图片
顺序一致性模型
JMM的内存模型
- JMM不保证64位 证书 与 浮点数的一致性。(原因与总线事务的原理有关,在32位系统中,64位的操作会被当做两个总线事务,但是一般的内存操作都是原子性的)
总线访问内存的方式:
处理器向总线发送总线事物的时候,是一块发到总线然后总线向内存发送事务
总线仲裁某个处理器发送的事务可以被处理其他事务暂时会被挂起。
Volatile关键字的特点是使本地内存失效 直接访问主存。写的时候则是直接把值刷入主存
Volatile的语义就是写线程A写完之后向将要读这个变量的B线程发送 v了消息
Volatile 对单个变量的操作具有原子性 锁是对整个代码段的读写具有原子性。
锁的语义:
线程a释放一个所实际是线程a对接下来要获取锁的线程b发送一个消息
线程b获取一个锁实际是b接收到了之前某个线程发出的消息
线程a释放所然后b获取锁实际上是线程a通过主存向b发送消息
JMM的设计意图是在于一个平衡