java内存模型详解-可见性

目录

JVM运行时数据区

作用:用来描述一个java进程里面的内存时什么样的情况。
java内存模型详解-可见性

Java内存模型 vs JVM运行时数据区

相关概念:
Java语言规范:用来描述java语言的特性。
java虚拟机规范:用来约束各个虚拟机的实现。
java内存模型:对java语言的描述。
JVM运行时数据区:对Java虚拟机规范的描述。
java内存模型详解-可见性

初看java内存模型

作用:主要用来描述多线程程序的语义(特性),描述多线程程序的规则。
java内存模型详解-可见性

多线程中的问题

  1. 所见非所得
  2. 无法肉眼去检测程序的准确性
  3. 不同的平台有不同的表现
  4. 错误很难重现
    java提出规范说明如何解决这些问题,JVM去实现这些规则。

从内存结构到内存模型

java内存模型详解-可见性
可见性问题
导致问题:写没有写进主内存;读没有从主内存中读取。

  1. cpu高速缓存和可见性的关系:
    虽然被写入缓存,但是另外一个线程可能无法被读到,即为可见性问题。
    java内存模型详解-可见性
  2. 指令重排序
    指令重排导致代码结果不可预估,可能会导致可见性问题。
    java内存模型详解-可见性

JIT编译器

JIT编译存在指令重排。
java内存模型详解-可见性
java内存模型详解-可见性

volatile关键字

作用:可以保证可见性问题,写完之后,后续的读可以读到最新的数据。
java内存模型(Java语言)对volatile的规则描述:
java内存模型详解-可见性
JVM对volatile关键字的描述:
java内存模型详解-可见性
只会对相关的volatile变量不做重排序,而不是所有的。
最终实现是由JVM来完成的。

Shared Variables(共享变量)定义

Java语言规范描述
:广义上的堆,指java语言规范的堆,包括方法区和堆内存,而不是jvm的堆内存。
java内存模型详解-可见性
线程间的操作的定义
感知:一个线程写,可以被另一个线程读到,即为感知。
资源竞争和线程间操作:同时有多个线程对同一个资源进行操作,其中至少有一个是写,则存在资源竞争,出现资源竞争后这样的一个操作称之为线程间操作
java内存模型详解-可见性
加锁和解锁也是多个线程的操作,会影响其它线程,也属于线程间的操作。

对于同步的规则定义

java内存模型详解-可见性
同步即为可见。
监视器主要针对于Synchronized。
默认值防止读到乱码或其它值。
启动线程 t1.start会修改线程状态的操作,t2会感知。
最后操作 t2线程执行完后,t1线程可见。
总结:不会被缓存,不会做相应的指令重排,保证可见性。

Happens-before先行发生原则

java内存模型详解-可见性

final在JMM中的处理

java内存模型中对final的描述规则。
构造版本即在构造函数中设置的值。如果没有用final修饰,可能看到的就是默认值。
java内存模型详解-可见性

Word Traring字节处理

不要多线程中对字节数组进行读写操作。
java内存模型详解-可见性

double和long的特殊处理

虽然JVM已经实现原子操作,但是java语言规范建议
java内存模型详解-可见性

再看Java内存模型

总结
java内存模型和JVM内存区域是完全不同的东西,不要混淆。
java内存模型解决java多线程中存在的以上问题。
volatile主要解决读写的可见性问题,禁止缓存指令重排
staitc不保证可见性,只是将数据存在方法区,而不是存在堆中。