Java内存模型
Java内存模型
概念:java内存模型定义了多线程之间共享变量的可见性以及如何在需要的时候对共享变量进行同步。
线程之间的通信
两种通信机制:
-
共享内存
写读内存中公共状态来通信,通过共享对象进行通信。
-
消息传递
明确的发送消息来进行通信,java中就是wait() notify().
java内存模型
-
首先,线程A把本地内存A中更新过的共享变量刷新到主内存中去。
-
然后,线程B到主内存中去读取线程A之前已更新过的共享变量。
-
线程A本地内存中的x值刷新到主内存中。
-
线程B从主内存中获取X的值并更新到本地内存中。
一个本地变量如果是原始类型,那么它会被完全存储到栈区。
一个本地变量也有可能是一个对象的引用,这种情况下,这个本地引用会被存储到栈中,但是对象本身仍然存储在堆区。
对于一个对象的成员方法,这些方法中包含本地变量,仍需要存储在栈区,即使它们所属的对象在堆区。
对于一个对象的成员变量,不管它是原始类型还是包装类型,都会被存储到堆区。
Static类型的变量以及类本身相关信息都会随着类本身存储在堆区。
堆中的对象可以被多线程共享。如果一个线程获得一个对象的应用,它便可访问这个对象的成员变量。如果两个线程同时调用了同一个对象的同一个方法,那么这两个线程便可同时访问这个对象的成员变量,但是对于本地变量,每个线程都会拷贝一份到自己的线程栈中。
共享对象的可见性
本地缓存没有同步到主缓存,就会导致其他线程无法看到修改后的内容。
要解决共享对象的可见性,可以使用volatile,volatile可以保证变量直接从内存读写。
竞争现象
主内存在两个不同的工作内存中副本进行变动,比如主存变量值为1,A工作内存+1,B工作内存+1,最终主存应该是3,但是并行处理中的A和B工作内存flush到主存,结果为2.
要解决这种问题,synchronized 保证同一时刻只有一个线程来执行,并保证变量从主从读,退出代码块,会flush到主存。
内存屏障(Memory Barrier )
- 保证特定操作的执行顺序。
- 影响某些数据(或则是某条指令的执行结果)的内存可见性。
Memory Barrier所做的另外一件事是强制刷出各种CPU cache,如一个Write-Barrier
(写入屏障)将刷出所有在Barrier之前写入 cache 的数据,因此,任何CPU上的线程都能读取到这些数据的最新版本。
如果一个变量是volatile
修饰的,JMM会在写入这个字段之后插进一个Write-Barrier
指令,并在读这个字段之前插入一个Read-Barrier
指令。这意味着,如果写入一个volatile
变量,就可以保证:
- 一个线程写入变量a后,任何线程访问该变量都会拿到最新值。
- 在写入变量a之前的写入操作,其更新的数据对于其他线程也是可见的。因为Memory Barrier会刷出cache中的所有先前的写入。
happens-before
如果一个操作的执行结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系,这个的两个操作既可以在同一个线程,也可以在不同的两个线程中。
- 程序顺序规则:一个线程中的每个操作,happens-before于该线程中任意的后续操作。
- 监视器锁规则:对一个锁的解锁操作,happens-before于随后对这个锁的加锁操作。
- volatile域规则:对一个volatile域的写操作,happens-before于任意线程后续对这个volatile域的读。
- 传递性规则:如果 A happens-before B,且 B happens-before C,那么A happens-before C。
两个操作之间具有happens-before关系,并不意味前一个操作必须要在后一个操作之前执行!仅仅要求前一个操作的执行结果,对于后一个操作是可见的,且前一个操作按顺序排在后一个操作之前。
相关文章
- JVM内存与垃圾回收篇第1章JVM和Java体系架构
- 金九银十准备季:Java IO流面试题(含答案)「建议收藏」
- java内存模型介绍[通俗易懂]
- java启动器_JAVA基础:Java 启动器如何查找类
- java 堆栈的声明_Java 堆栈[通俗易懂]
- MySQL字段类型如何转为java_Java JDBC中,MySQL字段类型到JAVA类型的转换
- java public interface_Java 接口interface的基础[通俗易懂]
- 【说站】Java内存交互如何操作
- JAVA外文参考文献_java参考文献近五年
- 八股文常客——Java内存模型JMM
- 读书笔记 | 类的使用 | Effective Java 3
- Java内存管理-JVM内存模型以及JDK7和JDK8内存模型对比总结(三)
- Java内存模型和线程安全
- 【Java】Best coding practices every java developer should
- Java 内存模型 JMM 浅析详解编程语言
- Java俄罗斯方块实现代码详解编程语言
- Java并发编程之内存模型详解编程语言
- Java基础之多线程实例详解编程语言
- Java内存模型浅析详解编程语言
- Java下使用Redis进行高效缓存优化(Redis缓存java)
- Java如何查询MySQL?25字(java查询mysql)
- Java操作Linux系统:让命令行更轻松(java操作linux)
- Linux下Java命令的使用方法简介(linux下java命令)
- Java加速Oracle开发之旅(java中oracle包)