JAVA内存模型(学习记录)
来源:互联网 发布:什么软件制作数据图表 编辑:程序博客网 时间:2024/06/06 11:37
一、java内存模型
java线程之间的通信是通过共享内存模型实现,这里的共享内存模型就是指java内存模型(JMM)。JMM决定了一个线程的变量何时对另一个变量可见。线程之间的共享变量存储在主内存中,而在线程的本地内存会存有共享变量的副本。通常来说,当A,B2个线程之间需要共享变量时,A线程先将本地内存改变后的变量副本刷新到主内存中,B线程在主内存中读取更新后的共享变量。
java内存区域的划分主要分为方法区、虚拟机栈,本地方法栈,堆,程序计数器。
1、方法区:存储被加载的类的信息,常量,静态变量,以及即时编译器编译后的代码等数据。
2、虚拟机栈:主要存放线程执行的局部变量表,操作数栈,动态链接,方法出口等信息,是线程私有的。其实内部存储的即是栈帧,栈帧只有最上部的处于活跃状态,栈帧与栈帧之间有重合部分,用于数据交换。
3、本地方法栈:是为了native方法服务,线程私有的。
4、堆:堆区用于存放所有的对象实例,可以被多线程共享。为了GC回收机制的方便,根据对象存活周期的长短将堆分为新生代和老生代。具体GC回收机制还没学习到。
5、程序计数器:当前线程执行的字节码信号指示器。当字节码解释器工作时,通过这个读取计数器的值来获取下一个需要执行的字节码指令。
java内存模型与硬件结构并不保持一致。在硬件方面,不分栈与堆,大多数数据都保存在内存中,少部分在CPU寄存器中。当对象和变量储存在计算器的各个内存中时,就会出现以下的问题:
1、共享对象的可见性
共享对象存储在主存中,当一个cpu的线程从缓存中将共享对象更改了,没有及时将更改后的对象flush到主存中,此时线程对共享对象的更改对其他线程就是不可见的。最终每个线程都会拷贝共享对象,而共享对象位于不同的cpu中。
解决这个问题需要使用volidate关键字,其会让线程对变量的读取直接来自主存。更新后会直接flush到主存,而不经过cpu缓存。
2、共享对象的竞争关系
当多个线程共享一个对象,它们同时修改这个共享对象时,就产生了竞争现象。
如果一个线程A从主存中获取共享obj到CPU缓存,线程B也读取共享obj到cpu缓存,如果两个线程都对obj中的变量进行加1操作,则obj的变量加1操作被执行了两次,只是缓存到了不同的cpu中。当两者是串行时,执行是正确的。但是当两者并行的时候,则不论是A还是B先执行flush将结果保存到主存中,最后的结果都是obj的变量增加了一次。
解决这个问题,就需要使用java的synchronized,ynchronized代码块可以保证同一个时刻只能有一个线程进入代码竞争区,synchronized代码块也能保证代码块中所有变量都将会从主存中读,当线程退出代码块时,对所有变量的更新将会flush到主存,不管这些变量是不是volatile类型的。
- JAVA内存模型(学习记录)
- java内存模型学习
- Java内存模型学习
- java学习系列4(内存模型)
- java 学习:Java内存模型
- JAVA 内存模型温故,随笔记录
- Java内存模型学习笔记
- java内存模型---学习笔记
- java内存模型学习笔记
- Java虚拟机学习 内存模型
- Java内存模型学习笔记
- Java多线程内存模型学习
- Java内存区域学习记录
- Java虚拟机学习之Java内存模型
- 【JAVA并发学习二】Java内存模型
- 深入学习java并发编程:内存模型(一)基础
- 深入学习java并发编程:内存模型(四)volatile
- 深入学习java并发编程:内存模型(五)锁
- 一个01字符串,求出现0、1出现次数相等的最长子串
- 多伦多大学联手Uber推出RevNet,不用存储激活便可实现反向传播
- Linux字符串检索
- unity AR3D物体识别
- unity——利用图片来生成字体
- JAVA内存模型(学习记录)
- AndroidStudio如何引入so包和更换默认目录
- 20-EMM Procedure 8&9. Handover & Cell Reselection with TAU
- SpringBoot+JPA(Hibernate)事物手动控制
- CADisplayLink
- Linux C语言高级编程之共享库(附测试案例)
- 制造业未来有多「智能」,12月长沙见分晓
- 多线程基础学习十:java.util.lock.concurrent.locks中lock
- Please select Android SDK