欢迎来到天天文库
浏览记录
ID:8966726
大小:329.00 KB
页数:22页
时间:2018-04-13
《java6中的线程优化真的有效么》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库。
1、Java6中的线程优化真的有效么?作者JeroenBorgers译者韩锴发布于2008年10月22日上午1时31分社区Java主题性能和可伸缩性标签并行计算,JVM,多线程,并发,JavaSE介绍—Java6中的线程优化Sun、IBM、BEA和其他公司在各自实现的Java6虚拟机上都花费了大量的精力优化锁的管理和同步。诸如偏向锁(biasedlocking)、锁粗化(lockcoarsening)、由逸出(escape)分析产生的锁省略、自适应自旋锁(adaptivespinning)这些特性,都是通过在
2、应用程序线程之间更高效地共享数据,从而提高并发效率。尽管这些特性都是成熟且有趣的,但是问题在于:它们的承诺真的能实现么?在这篇由两部分组成的文章里,我将逐一探究这些特性,并尝试在单一线程基准的协助下,回答关于性能的问题。相关厂商内容InfoQ中文站电子杂志《架构师》试刊号发布Java6中的线程优化真的有效么?技术沙龙:Solaris网络虚拟机构架和Grails框架分析(11.1杭州)SOYFramework:Java富客户端快速开发框架IDC:《软件商成长路线图》白皮书免费下载相关赞助商InfoQ中文站J
3、ava社区,关注企业Java社区的变化与创新,通过新闻、文章、视频访谈和演讲以及迷你书等为中国Java技术社区提供一流资讯。悲观锁模型Java支持的锁模型绝对是悲观锁(其实,大多数线程库都是如此)。如果有两个或者更多线程使用数据时会彼此干扰,这种极小的风险也会强迫我们采用非常严厉的手段防止这种情况的发生——使用锁。然而研究表明,锁很少被占用。也就是说,一个访问锁的线程很少必须等待来获取它。但是请求锁的动作将会触发一系列的动作,这可能导致严重的系统开销,这是不可避免的。我们的确还有其他的选择。举例来说,考虑
4、一下线程安全的StringBuffer的用法。问问你自己:是否你曾经明知道它只能被一个线程安全地访问,还是坚持使用StringBuffer,为什么不用StringBuilder代替呢?知道大多数的锁都不存在竞争,或者很少存在竞争的事实对我们作用并不大,因为即使是两个线程访问相同数据的概率非常低,也会强迫我们使用锁,通过同步来保护被访问的数据。“我们真的需要锁么?”这个问题只有在我们将锁放在运行时环境的上下文中观察之后,才能最终给出答案。为了找到问题的答案,JVM的开发者已经开始在HotSpot和JIT上进
5、行了很多的实验性的工作。现在,我们已经从这些工作中获得了自适应自旋锁、偏向锁和以及两种方式的锁消除(lockelimination)——锁粗化和锁省略(lockelision)。在我们开始进行基准测试以前,先来花些时间回顾一下这些特性,这样有助于理解它们是如何工作的。逸出分析—简析锁省略(Escapeanalysis-lockelisionexplained)逸出分析是对运行中的应用程序中的全部引用的范围所做的分析。逸出分析是HotSpot分析工作的一个组成部分。如果HotSpot(通过逸出分析)能够判断
6、出指向某个对象的多个引用被限制在局部空间内,并且所有这些引用都不能“逸出”到这个空间以外的地方,那么HotSpot会要求JIT进行一系列的运行时优化。其中一种优化就是锁省略(lockelision)。如果锁的引用限制在局部空间中,说明只有创建这个锁的线程才会访问该锁。在这种条件下,同步块中的值永远不会存在竞争。这意味这我们永远不可能真的需要这把锁,它可以被安全地忽略掉。考虑下面的方法:publicStringconcatBuffer(Strings1,Strings2,Strings3){,StringB
7、uffersb=newStringBuffer();sb.append(s1);sb.append(s2);sb.append(s3);returnsb.toString();}图1.使用局部的StringBuffer连接字符串如果我们观察变量sb,很快就会发现它仅仅被限制在concatBuffer方法内部了。进一步说,到sb的所有引用永远不会“逸出”到concatBuffer方法之外,即声明它的那个方法。因此其他线程无法访问当前线程的sb副本。根据我们刚介绍的知识,我们知道用于保护sb的锁可以忽略掉。从
8、表面上看,锁省略似乎可以允许我们不必忍受同步带来的负担,就可以编写线程安全的代码了,前提是在同步的确是多余的情况下。锁省略是否真的能发挥作用呢?这是我们在后面的基准测试中将要回答的问题。简析偏向锁(Biasedlockingexplained)大多数锁,在它们的生命周期中,从来不会被多于一个线程所访问。即使在极少数情况下,多个线程真的共享数据了,锁也不会发生竞争。为了理解偏向锁的优势,我们首先需要回顾一下如何获取锁(监视器)。
此文档下载收益归作者所有