JSR-133内存模型手册
1.介绍
JVM支持多种线程的执行,Threads代表的是线程类,位于java.lang.Thread包下,唯一的方式就是为用户在这个类下的对象创建线程,每一个线程关联着一个对象,一个线程将在start()调用时声明这个线程对象
在针对线程同步错误的情况下,手册描述了多线程程序的语义,包括了值位于只读内存在线程中更新的情况,这些都是基于内存模型下的语义规范,而这个文档主要讲述了内存模型.
这些语义并不是结束如何执行一个多线程程序,而描述多线程所表现的原理机制.
1.1 Locks
线程之间最基本的通信通过同步(synchronized)实现监控,每一个对象与一个监视器关联锁的状态,只有一个线程可以在监视器上控制一个锁,其他的线程会进入阻塞(blocked)状态,直到可以获取锁,有关锁的概念可以通过进行了解.
一个线程可以锁定一个特定监视器多次,每个逆转的锁会影响一个锁操作.
synchronized语句会计算对象的引用,然后尝试执行一个锁对象直到锁操作完成,在锁操作执行完后,synchronized会执行,当一个主方法执行完成后,会自动操作同一个监视器.
一个同步方法在调用后会自动执行锁方法,直到锁完成操作,当方法是一个是实例方法时,他会将调用实例所关联的监视器锁住,当方法是静态的,会将已经定义方法的类对象所关联的监视器锁住.如果执行方法主体已经完成,那么监视器会自动执行同一个操作.
语义并没有阻止和监测死锁发生,程序在遇到线程发生死锁条件,可以通过以下方式进行避免
- 互斥条:一个资源每次只被一个进程使用
- 请求于保持条件:一个进程因请求资源而阻塞时,对以获取的资源保持不放
- 不剥夺条件:进程已获得的资源,在未使用完后,不能强行剥夺
- 循环等待:将系统中所有资源设置标记来避免死锁
而在其他机制中,java提供了java.util.concurrent包来替代同步机制,concurrent详情可以查看进行了解
2.非正式语义
一个程序必须正确的在代码重排序之前避免错误的同步行为,synchronized不能保证绝对的准确性,但是他所带给程序的好处是可以减少程序的重排序行为.
有2个关键的思想来确定同步的正确性
Conflicting Accesses 两个读写访问同一个字段或者数组元素会保证至少有一个访问的操作
Happens-Before 关系 两个操作利用H-b来指定顺序,当一个动作处于h-b状态,那么第一个会在第二个之前显示,h-b关系不会必须发生在java平台中,H-B关系主要强调了两个动作方法之间的排序方式以及定义的方法.下面是H-B所包含的规则:
- 每个线程操作会对后续的线程进行Happens-Before
- 一个未加锁的监视器会对后续的监视器进行Happens-Before
- 一个Volatile字段的写操作会对后续的Volatile进行Happens-Before
- 在启动线程里start()方法的操作是都是Happens-before规则
- 在线程中发生Happens-before规则时成功后在线程中返回join()方法
- 当a H-B b ,b H-B c 则 a H-B c
3.1 顺序一致性
顺序一致性用于保证程序执行的可见性和排序,在一个顺序一致性行为时,在一个执行顺序一致,有一个全序个人行为(如读和写)这是符合程序的顺序。
每一个操作都具有原子性,每个线程都立即可见,如果程序没有数据竞争,那么所有执行的程序都具有顺序一致性,而作为之前提到的顺序一致性和数据竞争都需要知道原子的存在性.
当我们对内存模型使用顺序一致性时,许多编译器在优化时我们都要讨论他的合法性.
有顺序一致性所讨论的,我们可以使用它来提供一个重要的澄清关于数据竞争和正确同步的程序,竞态条件发生在处于相互冲突的同步排序下,一个程序在正确的同步状态下会消除竞态条件,所以,程序员只需要思考程序在顺序一致时是否处于正确的同步
3.2 Final字段
Final字段被定义为不可改变,详细的final语义可以清楚地知道与普通字段的区别,特别是在编译器具有同步屏障(synchronization barriers)去声明未知的方法,相应的,能保证final字段缓存不会重新加载.
Final字段也可以是线程安全的不可变对象保持不同步状态,一个线程安全的不可变对象被认为是不可变的,即使一个数据竞争时会在线程中引用不可变对象,这可以保证数据的安全.
Final字段必须保证不可变,一个对象在构造完成后完成初始化,线程只可以看到已经完成初始化后的final对象
在为构造器设置final字段时,不要其他地方引用该对象,线程会在构造函数完成时被看见,这会导致线程会只接收到正确构造版本的final字段,使数据保持不正确性
下面这个例子将展示普通字段与final字段的区别
4 什么是内存模型?
内存模型的被描述为一个程序和一个执行跟踪程序是程序的合法执行,在Java平台中,内存模型在每个只读跟踪程序每一个只读的监测和确认写操作是否遵循规则.
内存模型描述了程序中可能发生的行为,具体的表现是喜欢产生任意的代码,提供了大量的自由度来执行代码转换,包括重排遗迹不必要的同步.
再高级的行为中,非正式的内存模型可以显示当线程写操作显示另一个线程的规则中.
当我们在内存模型中使用"读"时,所指的是操作中的可读字段或者数组元素,在类似数组长度中读语义,调用虚拟方法中,不会影响数据竞争,jvm实现负责数据竞争不会导致错误,返回错误的数组长度或者虚方法调用导致的分割错误.
5.定义
共享变量/堆内存(Shared variables/Heap memory) 线程间可以互相共享的内存叫对内存,所有实例字段,静态字段以及数组元素都存储在堆内存中,我们用变量术语去引用全局字段和数组变量,一个方法中的局部变量在线程之间共享不会被内存模型所影响
线程内操作(Inter-thread Actions) 一个Inter-thread 操作可以执行监测 或影响另一个线程,Inter-Thread包含着读操作,共享变量的写操作和同步操作,加锁操作,还包含着与之交互的外部世界,和会导致线程进入无限循环.
我们不需要关心Inter-thread操作,正如前面提到的,每一个线程都具备Inter-thread语义,而任何Inter-thread都与执行的操作所关联,所有的操作都在程序中所操作的线程之间发生,关联的信息包括了
write read lock unlock
Program Order 所有的Inter-thread操作之间的线程,程序中线程的Program Order会给运行时环境足够的自由重排命令,此时的Program Order可以保证只能重排.
Intra-thread semantics 线程内语义时为单线程程序准备的,为了与线程的读操作得到预测,当线程的操作可以进行时,会在JLS定义线程上下文。
在每次确认线程是否为Intra-thread动作时,必须指定队列里的程序指向线程,如果为读操作,
通常将Intra-thread语义在从堆中读取值时隔离,他们在内存模型中确认存在.
Synchronization Actions 重量级锁包含锁,解锁,在volatile中读写操作,在开启线程时,任何在动作中开始或者在Synchronizeds-with中开启的节点都是重量级操作。
原文地址: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr133.pdf
JSR-133内存模型手册的更多相关文章
- 深入理解java内存模型
深入理解Java内存模型(一)——基础 深入理解Java内存模型(二)——重排序 深入理解Java内存模型(三)——顺序一致性 深入理解Java内存模型(四)——volatile 深入理解Java内存 ...
- 深入理解Java内存模型之系列篇
深入理解Java内存模型(一)——基础 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来 ...
- Java内存模型深度解析:基础部分--转
原文地址:http://www.codeceo.com/article/java-memory-1.html 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何 ...
- java内存模型-顺序一致性
数据竞争与顺序一致性保证 当程序未正确同步时,就会存在数据竞争.java 内存模型规范对数据竞争的定义如下: 在一个线程中写一个变量, 在另一个线程读同一个变量, 而且写和读没有通过同步来排序. 当代 ...
- java内存模型-基础
基础 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间 ...
- 【Todo】【转载】深入理解Java内存模型
提纲挈领地说一下Java内存模型: 什么是Java内存模型 Java内存模型定义了一种多线程访问Java内存的规范.Java内存模型要完整讲不是这里几句话能说清楚的,我简单总结一下Java内存模型的几 ...
- 深入理解Java内存模型(一)——基础(转)
转自程晓明的"深入理解Java内存模型"的博客 http://www.infoq.com/cn/articles/java-memory-model-1 并发编程模型的分类 在并发 ...
- 深入理解Java内存模型(一)——基础
并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信 ...
- 【转】深入理解Java内存模型(一)——基础
并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信 ...
随机推荐
- 注意特殊情况!最长上升子序列!!poj2533
poj 2533 简单的动归.用O(n^2)的算法也能过.但是有个细节!刚开始ans初始化为0时是错的!!!要初始化为1.因为只有1个数的时候,下面的循环是不会执行的.....或者特判.. #incl ...
- Android EditText____TextchangedListener
今天在做APP的时候有个需求: EditText 动态监听内容变化如果长度为6时(就是看是不是验证码) 判断是否正确 正确就跳到下一个Activity,但是在Activity.finish()的时候, ...
- 阿里开源!轻量级深度学习端侧推理引擎 MNN
阿里妹导读:近日,阿里正式开源轻量级深度学习端侧推理引擎“MNN”. AI科学家贾扬清如此评价道:“与 Tensorflow.Caffe2 等同时覆盖训练和推理的通用框架相比,MNN 更注重在推理时的 ...
- AIDL基本用法
1. AIDL有什么用?用TA到目的是什么? 2. 怎么用AIDL? 1. AIDL有什么用? 1.1. 为了提高代码执行速度,将部分逻辑封入C/C++代码中 1.2. 为了调用这部分代码,使用JN ...
- jQuery 练习 dom
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Android教程 -09 数据的持久化存储
视频为本篇播客知识点讲解,建议采用超清模式观看, 欢迎点击订阅我的优酷 任何一个程序其实说白了就是在不停地和数据打交道,数据持久化就是指将那些内存中的瞬时数据保存到存储设备中,保证及时手机关机的情况下 ...
- 在SpringBoot中使用JWT
JWT简介 简介 JSON Web token简称JWT, 是用于对应用程序上的用户进行身份验证的标记.也就是说, 使用 JWTS 的应用程序不再需要保存有关其用户的 cookie 或其他sessio ...
- lavarel 响应宏
宏的概念 计算机里的宏是批量处理的意思.比如我们在进行文本编辑的时候,打错字会有回退的功能——control+z:但是这是我们的键盘操作,计算机在进行处理的时候是不能理解的,他必须对最近两次操作进行比 ...
- Tomcat停,图片名字中文显示不出来
Tomcat停,图片名字中文显示不出来 Tomcat下,图片名字中文显示不出来在tomcat的server.xml中加入URIEncoding="utf-8"<Con ...
- 4-3 调试代码命令 scrapy shell http://blog.jobbole.com/114496/(入口url)
调试代码命令 scrapy shell http://blog.jobbole.com/114496/(入口url)