java 对象内存模型

基础

在Java中,所有实例域(成员变量/成员方法)、静态域和数组元素存储在堆内存中,堆内存在线程之间共享,会存在内存可见性问题,受内存模型影响

Java内存模型的主要目标是定义程序中堆内存变量的访问规则,线程之间的通信和同步由Java内存模型控制

主内存与工作内存

java内存模型规定了所有的实例域(成员变量/成员方法)、静态域和数组元素都存储在主内存中, 除此之外每个线程都有自己的工作内存, 线程的工作内存中保存了被该线程使用到的变量的副本拷贝, 线程对变量的所有操作(读取, 赋值等)都必须在工作内存中进行, 而不能直接读写主内存中的变量. 不同的线程之间也无法直接访问对方工作内存中的变量, 线程间变量值的传递均需要通过主内存来完成

重排序

为了提高程序执行的性能,编译器和处理器通常会对指令做重排序

1属于编译器重排序,2和3属于处理器重排序

这些重排序都可能导致多线程程序出现内存可见性问题,为了避免这些问题,JMM的重排序规则会禁止特定类型的重排序

JMM的编译器重排序规则会禁止特定类型的编译器重排序;JMM的处理器重排序规则会要求Java编译器在生成指令序列时,通过插入特定类型的内存屏障指令来禁止特定类型的处理器重排序

JMM属于语言级的内存模型,它确保在不同的编译器和处理器平台上,通过禁止特定类型的编译器和处理器重排序,为程序员提供一致的内存可见性保证

Volatile与Synchronized

对于volatile修饰的变量,当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的

volatile变量对所有线程是立即可见的,对volatile变量的所有写操作都能立刻反应到其他线程之中

JVM规范规定了任何一个线程修改了volatile变量的值都需要立即将新值更新到主内存中, 任何线程任何时候使用到volatile变量时都需要重新获取主内存的变量值

两者区别

1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
3.volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
5.volatile标记的变量不会被编译器优化(禁止指令重排序优化,即执行顺序与程序顺序一致);synchronized标记的变量可以被编译器优化

 

 

 

猜你喜欢

转载自blueskator.iteye.com/blog/2227011
今日推荐