版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、java内存模型-编程开发技术java内存模型原文出处:朱小厮question:在并发编程中,多个线程之间采取什么机制进行通信(信息交换), 什么机制进行数据的同步?answer:在java语言屮,采用的是共享内存模型来实现多线程z间的信息交换 和数据同步的。线程之间通过共享程序公共的状态,通过读-写内存中公共状态的方式来进行隐 式的通信。同步指的是程序在控制多个线程之间执行程序的相对顺序的机制,在 共享内存模型屮,同步是显式的,程序员必须显式指定某个方法/代码块需要在 多线程之间互斥执行。概述java内存模型的主要目标是定义程序中各个变量的访问规则,即在jvm中将变 量存储到内存和从内存中取
2、出变量这样的底层细节。此处的变量与java编程里 而的变量冇所不同,它包含了实例字段、静态字段和构成数组对彖的元素,但不 包含局部变量和方法参数,因为后者是线程私有的,不会共享,当然不存在数据 竞争问题(如果局部变量是一个reference引用类型,它引用的对象在java堆 中口j被各个线程共享,但是reference引用本身在java栈的局部变量表中,是 线程私有的)。为了获得较高的执行效能,j3v3内存模型并没有限制执行引起 使用处理器的特定寄存器或者缓存来和主内存进行交互,也没冇限制即时编译器 进行调整代码执行顺序这类优化措施。jmm规定了所有的变量都存储在主内存(main memory
3、)中。每个线程还有自己 的工作内存(working memory),线程的工作内存中保存了该线程使用到的变量 的主内存的副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作 内存中进行,而不能直接读写主内存中的变量(volat订e变量仍然有工作内存 的拷贝,但是由于它特殊的操作顺序性规定,所以看起来如同直接在主内存中 读写访问一般)。不同的线程之间也无法直接访问对方工作内存中的变量,线程之间值的传递都需要通过主内存来完成。javal工作内存1java线程2<=«>工作内存2java线程3 y工作内存3sava 和 load 操作线程1和线程2要想进行数据的交换一般要
4、经历下面的步骤:1. 线程1把工作内存1中的更新过的共享变量刷新到主内存中去。2. 线程2到主内存小去读取线程1刷新过的共享变量,然后copy 一份到工作内 存2中去。内存模型的特性java内存模型是围绕着并发编程中原子性、可见性、有序性这三个特征來建立 的,那我们依次看一下这三个特征: 原子性(atomicity) 原子性是指一个操作不能被打断,要么全部执行完毕,要么不执行。在这点上有 点类似于事务操作,要么全部执行成功,要么回退到执行该操作之前的状态。基本类型数据的访问大都是原了操作,long和double类型的变量是64位,但 是在32位jvm屮,32位的jvm会将64位数据的读写操作分
5、为2次32位的读写 操作来进行,这就导致了 long、double类型的变量在32位虚拟机中是非原子操 作,数据有可能会被破坏,也就意味着多个线程在并发访问的吋候是线程非安全 的。下而我们来演示这个32位jvm下,对64位long类型的数据的访问的问题:public class notatomicity /静态变量tpublic static long t = 0;/静态变量t的get方法 public static long gett() return t;/静态变量t的set方法 public static void sett(1ong t) notatomicity. t 二 t;改变变
6、量t的线程 public static class changet implements runnable private long to;public changet(long to) this to = to; public void run() 不断的将long变量设值到t屮 whi1e (true) notatomicity sett(to);将当前线程的执行时间片段让岀去,以便由线程调度机制重 新决定哪个线程可以执行thread, yield();读取变量t的线程,若读取的值和设置的值不一致,说明变量t的数据被 破坏了,即线程不安全public static class readt
7、implements runnablepublic void run() /不断的读取notatomicity的t的值 while (true) long tmp 二 notatomicity.gett(); 比较是否是自己设值的其中一个 if (tmp != 100l && tmp != 200l && tmp != -300l && tmp != -400l) 程序若执行到这里,说明long类型变量t,其数据已 经被破坏了system, out. printin(tmp);/将当前线程的执行时间片段让岀去,以便由线程调度机制 重新决定哪个线程
8、可以执行thread, yield();public static void main(string args) new thread (new changct(lool)start(); new thread (new change? (200l). start(); new thread (new changet (-300l). start(); new thread (new changet (-400l). start(); new thread (new readt (). start ();我们创建了 4个线程來对long类型的变量t进行赋值,赋值分别为100, 200, -30
9、0, -400,有一个线程负责读取变量i,如果正常的话,读取到的i的值应该 是我们赋值中的一个,但是在32的jvm中(ps: 64位的就别想了),事情会出 乎预料。如果程序正常的话,我们控制台不会有任何的输岀,可实际上,程序一 运行,控制台就输岀了下面的信息:-42949670964294966896-4294967096-42949670964294966896之所以会出现上面的情况,是因为在32位jvm中,64位的long数据的读和写 都不是原子操作,即不具有原子性,并发的吋候相互干扰了。32位的jvm中,要想保证对long、double类型数据的操作的原子性,可以对访 问该数据的方法进行
10、同步,就像下而的:public class atomicity /静态变量tpublic static long t 二 0;静态变量t的get方法,同步方法 public synchronized static long gett() return t;静态变量t的set方法,同步方法 public synchronized static void sett(1ong t) atomicity, t 二 t;改变变量t的线程 public static class changet implements runnable private long to;public changet(long
11、to) this, to = to; public void run() 不断的将long变量设值到t中 while (true) atomicity sett(to);将当前线程的执行时间片段让出去,以便由线程调度机制重 新决定哪个线程可以执行thread yield();读取变量t的线程,若读取的值和设置的值不一致,说明变量t的数据被 破坏了,即线程不安全public static class rcadt implcmcnts runnablepublic void run() /不断的读取notatomicity的t的值whi1e (true) long tmp = atomicityg
12、ctt(); 比较是否是t己设值的其屮一个if (tmp != 100l && tmp != 200l && tmp != -300l && tmp != -400l) /程序若执行到这里,说明long类型变量t,其数据已 经被破坏了system out println(tmp);/将当前线程的执行吋间片段让出去,以便由线程调度机制 重新决定哪个线程口j以执行thread yield ();public static void main(string args) new thread(new changet(100l). start(); new
13、 thread (new changet (200l). start(); new thread (new changet (-300l). start(); new thread (new changet (-400l). start(); new thread (new readt (). start ();这样做的话,可以保证对64位数据操作的原子性。可见性一个线程对共享变量做了修改z后,其他的线程立即能够看到(感知到)该变量 这种修改(变化)。java内存模型是通过将在工作内存中的变量修改后的值同步到主内存,在读取 变量前从主内存刷新最新值到工作内存小,这种依赖主内存的方式来实现可见性
14、 的。无论是普通变量还是volatile变量都是如此,区别在于:volatile的特殊规则 保证了 volatile变量值修改后的新值立刻同步到主内存,每次使用volatile 变量前立即从主内存中刷新,因此volatile保证了多线程之间的操作变量的可 见性,而普通变量则不能保证这一点。除了 volatile关键字能实现可见性之外,还有synchronized, lock, final也是 可以的。使用synchronized关键字,在同步方法/同步块开始时(monitor enter),使用 共享变量时会从主内存中刷新变量值到工作内存中(即从主内存中读取最新值到 线程私有的工作内存中),在
15、同步方法/同步块结束时(monitor exit),会将工作 内存屮的变量值同步到主内存屮去(即将线程私冇的工作内存屮的值写入到主内 存进行同步)。使用lock接口的最滋用的实现reentrantlock(重入锁)来实现可见性:当我们 在方法的开始位置执行lock. lock()方法,这和synchronized开始位置(monitor enter)有相同的语义,即使用共享变量时会从主内存小刷新变量值到工作内存 屮(即从主内存中读取最新值到线程私有的工作内存中),在方法的最后finally 块里执行 lock, unlock()方法,和 synchronized 结束位置(monitor ex
16、it)有 相同的语义,即会将工作内存中的变量值同步到主内存中去(即将线程私有的工 作内存中的值写入到主内存进行同步)。fineil关键字的可见性是指:被final修饰的变量,在构造函数数一旦初始化完 成,并冃在构造函数屮并没冇把“this”的引用传递出去(“this”引用逃逸是 很危险的,其他的线程很可能通过该引用访问到只“初始化一半”的对象),那 么其他线程就可以看到final变量的值。有序性对于一个线程的代码而言,我们总是以为代码的执行是从前往后的,依次执行的。 这么说不能说完全不对,在单线程程序里,确实会这样执行;但是在多线程并发 时,程序的执行就有可能出现乱序。用一句话可以总结为:在木
17、线程内观察,操 作都是有序的;如果在一个线程中观察另外一个线程,所有的操作都是无序的。 前半句是指“线程内表现为串彳亍语义(within thread as-辻-serial semantics)",后半句是指“指令重排”现象和“工作内存和主内存同步延迟” 现象。java捉供了两个关键字volatile和synchronized来保证多线程z间操作的冇 序性,volatile关键字本身通过加入内存屏障来禁止指令的重排序,而 synchronized关键字通过一个变量在同一吋间只允许有一个线程对其进彳亍加锁 的规则來实现,在单线程程序中,不会发生“指令重排”和“工作内存和主内存 同步延
18、迟”现象,只在多线程程序中出现。happens-before 原则java内存模型中定义的两项操作之间的次序关系,如果说操作a先行发生于操 作b,操作a产生的影响能被操作b观察到,“影响”包含了修改了内存屮共享 变量的值、发送了消息、调用了方法等。卜面是jqvb内存模型卜'一些”天然的uhappens-before关系,这些 happens-before关系无须任何同步器i办助就已经存在,可以在编码屮直接使用。 如果两个操作之间的关系不在此列,并且无法从下列规则推导出来的话,它们就 没有顺序性保障,虚拟机可以对它们进行随意地重排序。1. 程序次序规则(pragram order rule):在一个线程内,按照程序代码顺序,书写在 前面的操作先行发生于书写在后面的操作。准确地说应该是控制流顺序而不是程序 代码顺序,因为要考虑分支、循环结构。2. 管程锁定规则(monitor lock rule): 一个unlock操作先彳亍发生于后面对同一个锁的 lock操作。这里必须强调的是同一个锁,而”后而“是指时间上的先后顺序。3. volatile变量规贝0(volatile variable rule):对*个volatile变量的写操作先行发牛于 后面对这个变量的读取操作,这里的'
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 急诊科护士考试题及答案
- 2025年缓控释制剂题库级及答案
- 2025年合肥化学竞赛题库及答案
- 专四考试韩语真题及答案
- 2025生特储能招聘题目及答案
- 2025审计招聘题库及答案
- 2025复印机采购合同模板
- 2025热管理仿真岗招聘笔试题及答案
- 2025渠道销售秋招面试题及答案
- 2025秋招:智能制造技术岗题目及答案
- (高清版)DZT 0275.5-2015 岩矿鉴定技术规范 第5部分:矿石光片鉴定
- 2024年水文勘测工技能知识竞赛笔试历年真题荟萃含答案
- 分体空调维保技术标书(分体空调维护保养技术标书)
- 药事法规课件
- 律师的招聘简章文件
- DL-T 300-2022 火电厂凝汽器及辅机冷却器管防腐防垢导则
- 共青团团课主题班会课件PPT模板PPT
- GB/T 3033.1-2005船舶与海上技术管路系统内含物的识别颜色第1部分:主颜色和介质
- GA/T 1173-2014即时通讯记录检验技术方法
- GA 1800.2-2021电力系统治安反恐防范要求第2部分:火力发电企业
- 工程案例-金域华府住宅小区
评论
0/150
提交评论