Java多线程中的内存模型
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6536131.html
一:现代计算机的高速缓存
在计算机组成原理中讲到,现代计算机为了匹配 计算机存储设备的读写速度 与 处理器运算速度,在CPU和内存设备之间加入了一个名为Cache的高速缓存设备来作为缓冲:将运算需要用到的数据从内存复制到cache中,CPU可以在运算期间对cache进行高速的读写操作,运算结束后在从cache把数据同步回内存。
Cache引出了一个新问题:缓存一致性。每个处理器有自己的cache,而他们又共享一个主内存。当多个处理器的运算任务都设计同一内存区域时,将会导致各自的缓存数据不一致。那么,在各自运算结束后,以谁的缓存数据为准同步回主存呢?此时,就需要 缓存一致性协议 来制定多个处理器对统一内存区域的读写操作了。
除了Cache,为了更好地利用处理器资源,处理器还会对代码进行 乱序执行 ,在最后才把结果重组使得结果与顺序执行一致。
二:Java内存模型的类比
类比与现代计算机的主存与cache,JVM中规定了 所有变量都存储在主内存中(类比计算机的主存),然后每条线程有自己的工作内存(类比每个处理器的cache)。线程的工作内存中保存了该线程需要用到的变量的拷贝值,线程在CPU上运行时都是对自己工作线程中的数据进行读写操作,运行结束之后才把数据同步化主内存中。那么类比于计算机使用 缓存一致性协议 解决缓存一致性问题,JVM中就需要线程同步机制来达到多线程对同一内存区域的读写控制了。
此外,Java编译器为了提高性能,采取了 指令重排序(类比计算机的 乱序执行),若多个线程都有语句对同一内存区域进行操作的话,有可能因为指令重排序而导致结果不符预料。因此,也需要线程同步机制来达到多线程对同一内存区域的读写控制。
三:主内存与工作内存的数据交互
JVM定义了8种操作来完成主内存与线程工作内存的数据交互:
1:lock:把主内存变量标识为一条线程独占,此时不允许其他线程对此变量进行读写。
2:unlock:解锁一个主内存变量。
3:read:把一个主内存变量值读入到线程的工作内存,强调的是读入这个过程。
4:load:把read到变量值保存到线程工作内存中作为变量副本,强调的是读入的值的保存过程。
5:use:线程执行期间,把工作内存中的变量值传给字节码执行引擎。
6:assign(赋值):字节码执行引擎把运算结果传回工作内存,赋值给工作内存中的结果变量。
7:store:把工作内存中的变量值传送到主内存,强调传送的过程。
8:write:把store传送进来的变量值写入主内存的变量中,强调保存的过程。
JVM要求以上8个操作都具有原子性,即对数据的读写操作具有原子性。但也有例外,即:long、double的非原子性协定:这两个64位类型的数据的读、写操作各需两次进行,一次读/写 32 位,这两次读/两次写 是不保证原子性的。
四:原子性、可见性、有序性
原子性:基本数据类型的读写操作是原子性的;更大范围的(代码块)的原子性可以用lock、unlock操作来实现(上锁后就只有一个线程来执行了,所以不会被其他线程打断原子操作),表现到代码层面就是使用syncrhoized同步块。
可见性:当一个线程修改了被多线程共享的一个主内存变量值时,其他线程能立刻知道这个修改。
我们在上面可以知道,JVM是通过工作内存中的变量值变化后,把新值同步会主内存,然后其他线程从主内存读取这个新值来实现可见性的。这里有个区别:普通变量的值变化后,不一定会立刻同步会主内存,而是会等线程执行完或者一段时间后才同步会,而且同步回主内存后,其他线程的工作内存也不一定会立刻读取新值。而被volatile关键字修饰的变量,一旦在工作内存中被修改,则立刻同步回主内存,并且其他使用了这个变量的线程的工作内存会立刻从主内存读取新值。而syncrhoized关键字修饰的变量由于一次只能有一个线程能使用,故一次也只能有一个工作线程读写它,所以也能“纵向”地实现可见性。
有序性:多线程之间对共享数据的操作的有序性,可以通过volatile和syncrhoized关键字来保证。volatile关键字禁止了指令重排序,而syncrhoized关键字规定了多个线程每次只能有一个线程对共享数据进行操作。
五:volatile关键字
一个volatile变量具有两种特性:可见性、禁止指令重排序。但是,volatile不具备原子性!原因是volatile变量的值可以被多线程交替修改,而修改包括了read、load、use、store、write等过程,这些过程不能保证是原子执行的。
可见性:被volatile关键字修饰的变量,一旦在工作内存中被修改,则立刻同步回主内存,并且其他使用了这个变量的线程的工作内存会立刻从主内存读取新值。
禁止指令重排序:volatile变量在赋值后会创建一个内存屏障:指令重排序时,位于后面的指令不能排到内存屏障之前。
Java多线程中的内存模型的更多相关文章
- [心得笔记]Java多线程中的内存模型
一:现代计算机的高速缓存 在计算机组成原理中讲到,现代计算机为了匹配 计算机存储设备的读写速度 与 处理器运算速度,在CPU和内存设备之间加入了一个名为Cache的高速缓存设备来作为缓冲:将运算需要 ...
- java多线程中的三种特性
java多线程中的三种特性 原子性(Atomicity) 原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行. 如果一个操作时原子性的,那么多线程并 ...
- (转载)JVM中的内存模型与垃圾回收
转载自微信公众号:Java高级架构(Java-jiagou)-----看完这篇文章,我奶奶都知道JVM中的内存模型与垃圾回收了! 六.内存模型 6.1 内存模型与运行时数据区 Java虚拟机在执行J ...
- 【java虚拟机】jvm内存模型
作者:pengjunlee原文链接:https://blog.csdn.net/pengjunlee/article/details/71909239 目录 一.运行时数据区域 1.程序计数器 2.J ...
- Java虚拟机学习 - 体系结构 内存模型
一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代” .“非堆”, 它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内存区域.默认最小值为16MB,最 ...
- Java虚拟机中的内存分配
java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途以及创建和销毁的时间. 栈:存放的是局部变量,包括:1.用来保存基本数据类型的值:2.保存类 ...
- Java虚拟机学习 - 体系结构 内存模型(1)
一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代" ."非堆", 它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内 ...
- Java虚拟机学习 - 体系结构 内存模型(转载)
一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代” .“非堆”, 它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内存区域.默认最小值为16MB, ...
- Java:JVM的内存模型
JVM内存模型 JVM内存模型可以分为两个部分,如下图所示,堆和方法区是所有线程共有的,而虚拟机栈,本地方法栈和程序计数器则是线程私有的. 1. 堆(Heap) 堆内存是所有线程共有的,可以分为两 ...
随机推荐
- 抄袭证据之中的一个CMM与CMMI的名称
以下文字来自我即将完毕的文章,谢博士说她没有抄袭,可是文中实在是有太多的漏洞了. 6.2.7 P120页中: "实际上终于所谓的统一方法论就是标准,尽管作标准并非目的.但标准是必须有的.能够 ...
- MongoDB索引,性能分析
索引的限制: 索引名称不能超过128个字符 每个集合不能超过64个索引 复合索引不能超过31列 MongoDB 索引语法 db.collection.createIndex({ <field&g ...
- [C#技术] DataSet(DataTable)轻松的通过Sum、Aver、Count等统计出相关结果
我们在使用Sql ******这些数据库时,可以轻松的通过Sum.Aver.Count等统计出相关结果,那么,在已经把数据检索出来的DataSet(DataTable)中呢?特别是通过Web Serv ...
- Error:Program type already present: android.arch.lifecycle.LiveData
Apparently, this is intended behavior: com.firebaseui:firebase-ui-firestore:3.1.0 depends on android ...
- Check failed: mdb_status == 0 (13 vs. 0) Permission denied
文件权限问题. chown或者chmod即可 另外注意lmdb文件的权限
- CDR话单主要字段介绍
l Time of call connection RRC连接时的时间,格式:yyyy年mm月dd日hh时mm分ss秒 l Call Setup Time per sections 呼叫建立时长 ...
- Spring RestTemplate中几种常见的请求方式GET请求 POST请求 PUT请求 DELETE请求
Spring RestTemplate中几种常见的请求方式 原文地址: https://blog.csdn.net/u012702547/article/details/77917939 版权声明 ...
- 奇怪吸引子---Finance
奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...
- lftp命令
lftp 是一个功能强大的下载工具,它支持访问文件的协议: ftp, ftps, http, https, hftp, fish.(其中ftps和https需要在编译的时候包含openssl库).ll ...
- Emscripten教程之连接C++和JavaScript(三)
本文是Emscripten-WebAssembly专栏系列文章之一,更多文章请查看专栏.也可以去作者的博客阅读文章.欢迎加入Wasm和emscripten技术交流群,群聊号码:939206522. E ...