电脑桌面
添加小米粒文库到电脑桌面
安装后可以在桌面快捷访问

深入Java底层:内存屏障与JVM并发详解——北大青鸟佳音旗舰VIP免费

深入Java底层:内存屏障与JVM并发详解——北大青鸟佳音旗舰_第1页
1/7
深入Java底层:内存屏障与JVM并发详解——北大青鸟佳音旗舰_第2页
2/7
深入Java底层:内存屏障与JVM并发详解——北大青鸟佳音旗舰_第3页
3/7
http://www.bjaccp.com深入Java底层:内存屏障与JVM并发详解内存屏障,又称内存栅栏,是一组处理器指令,用于实现对内存操作的顺序限制。本文假定读者已经充分掌握了相关概念和Java内存模型,不讨论并发互斥、并行机制和原子性。内存屏障用来实现并发编程中称为可见性(visibility)的同样重要的作用。内存屏障为何重要?对主存的一次访问一般花费硬件的数百次时钟周期。处理器通过缓存(caching)能够从数量级上降低内存延迟的成本这些缓存为了性能重新排列待定内存操作的顺序。也就是说,程序的读写操作不一定会按照它要求处理器的顺序执行。当数据是不可变的,同时/或者数据限制在线程范围内,这些优化是无害的。如果把这些优化与对称多处理(symmetricmulti-processing)和共享可变状态(sharedmutablestate)结合,那么就是一场噩梦。当基于共享可变状态的内存操作被重新排序时,程序可能行为不定。一个线程写入的数据可能被其他线程可见,原因是数据写入的顺序不一致。适当的放置内存屏障通过强制处理器顺序执行待定的内存操作来避免这个问题。内存屏障的协调作用内存屏障不直接由JVM暴露,相反它们被JVM插入到指令序列中以维持语言层并发原语的语义。我们研究几个简单Java程序的源代码和汇编指令。首先快速看一下Dekker算法中的内存屏障。该算法利用volatile变量协调两个线程之间的共享资源访问。请不要关注该算法的出色细节。哪些部分是相关的?每个线程通过发信号试图进入代码第一行的关键区域。如果线程在第三行意识到冲突(两个线程都要访问),通过turn变量的操作来解决。在任何时刻只有一个线程可以访问关键区域。1.//coderunbyfirstthread//coderunbysecondthread2.3.1intentFirst=true;intentSecond=true;4.25.3while(intentSecond)while(intentFirst)//volatileread6.4if(turn!=0){if(turn!=1){//volatileread7.5intentFirst=false;intentSecond=false;8.6while(turn!=0){}while(turn!=1){}9.7intentFirst=true;intentSecond=true;10.8}}11.912.10criticalSection();criticalSection();13.1114.12turn=1;turn=0;//volatilewrite15.13intentFirst=false;intentSecond=false;//volatilewrite硬件优化可以在没有内存屏障的情况下打乱这段代码,即使编译器按照程序员的想法顺序列出所有的内存操作。考虑第三、四行的两次顺序volatile读操作。每一个线程检查其他线程是否发信号想进入关键区域,然后检查轮到谁操作了。考虑第12、13行的两次顺序写操作。每一个线程把访问权释放给其他线程,然后撤销自己访问关键区域的意图。读线程应该从不期望在其他线程撤销访问意愿后观察到其他线程对turn变量的写操作。这是个灾难。但是如果这些变量没有volatile修饰符,这的确会发生!例如,没有volatile修饰符,第二个线程在第一个线程对turn执行写操作(倒数第二行)之前可能会观察到第一个线程对intentFirst(倒数第一行)的写操作。关键词volatile避免了这种情况,因为它在对turn变量的写操作和对intentFirst变量的写操http://www.bjaccp.com作之间创建了一个先后关系。编译器无法重新排序这些写操作,如果必要,它会利用一个内存屏障禁止处理器重排序。让我们来看看一些实现细节。PrintAssemblyHotSpot选项是JVM的一个诊断标志,允许我们获取JIT编译器生成的汇编指令。这需要最新的OpenJDK版本或者新HotSpotupdate14或者更高版本。通过需要一个反编译插件。Kenai项目提供了用于Solaris、Linux和BSD的插件二进制文件。hsdis是另一款可以在Windows通过源码构建的插件。两次顺序读操作的第一次(第三行)的汇编指令如下。指令流基于Itanium2多处理硬件、JDK1.6update17。本文的所有指令流都在左手边以行号标记。相关的读操作、写操作和内存屏障指令都以粗体标记。建议读者不要沉迷于每一行指令。16.10x2000000001de819c:addsr37=597,r36;;;...8411255417.20x2000000001de81a0:ld1.acqr38=[r37];;;...0b30014aa01018.30x2000000001de81a6:nop.m0x0;...0000000200c019.40x2000000001de81ac:sxt1r38r38=r38;;;...0051300420.50x2000000001de81b0:cmp4.eqp0,p6=0,r38;...1100004c863921....

1、当您付费下载文档后,您只拥有了使用权限,并不意味着购买了版权,文档只能用于自身使用,不得用于其他商业用途(如 [转卖]进行直接盈利或[编辑后售卖]进行间接盈利)。
2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。
3、如文档内容存在违规,或者侵犯商业秘密、侵犯著作权等,请点击“违规举报”。

碎片内容

深入Java底层:内存屏障与JVM并发详解——北大青鸟佳音旗舰

确认删除?
VIP
微信客服
  • 扫码咨询
会员Q群
  • 会员专属群点击这里加入QQ群
客服邮箱
回到顶部