Java8中CAS的增强-编程开发技术_第1页
Java8中CAS的增强-编程开发技术_第2页
Java8中CAS的增强-编程开发技术_第3页
Java8中CAS的增强-编程开发技术_第4页
Java8中CAS的增强-编程开发技术_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、java8中cas的增强-编程 开发技术java8 中 cas的增强原文出处:trytocatch几天前,我偶然地将之询写的用來测试atomictnteger和synchronized的自増 性能的代码跑了一卜,意外地发现atomiclntcgcr的性能比synchronized更好 了,经过一番原因查找,冇了如下发现:在 jdkl. 7 中,atomiclnteger 的 getandlncrement 是这样的:public final int getandlncrement() for (; ;) int current = get ();int next = current + 1;i

2、f (compareandset(current, next)return current;public final boolean compareandset(int expect, int update) return unsafe. compareandswapint(this, valueoffset, expect, update); 而在jdkl. 8中,是这样的:public final int getandlncrement() return unsafe.getandaddlnt(this, valueoffset, 1);口j以看出,在jdkl. 8中,直接使用了 unsa

3、fe的getandaddlnt方法,而在jdkl. 7 的unsafe中,没有此方法。(ps:为了找出原因,我反编译了 unsafe,发现cas 的失败重试就是在getandaddlnt方法里完成的,我用反射获取到unsafe实例, 编写了跟getandaddlnt相同的代码,但测试结果却跟jdkl. 7的 getandlncrement 样慢,不知道unsafe里面究竟玩了什么黑魔法,还请高人 不吝指点)(补充:文章末尾已有推论)通过查看atomictnteger的源码口j以发现,受影响的还冇get/ndadd> addandget 等大部分方法。有了这次对cas的增强,我们又多了一个

4、使用非阻塞算法的理由。最后给出测试代码,需要注意的是,此测试方法简单粗暴,compareandset的性 能不如synchronized,并不能简单地说synchronized就更好,两者的使用方式 是存在差异的,而且在实际使用中,还冇业务处理,不可能冇如此高的竞争强度, 此对比仅作为一个参考,该测试能够证明的是,atomic integer. getandlncrement 的性能有了大幅提升。package performanee;import java utii. concurrent countdownlatch; import java utii.concurrent atomic

5、atomiclnteger; import java.util.concurrent. locks. locksupport;public class atomictest /测试规模,调用一次gctandlncreascx视作提供一次业务服务,记录 提供test_s1ze次服务的耗时private static final int test_size 二 100000000;/客户线程数private static final int tiiread_count = 10;/使用countdownlatch让齐线程同时开始 private countdownlatch cdl = new c

6、ountdownlatch(threadcount +1); _private int n = 0;privatc atomiclnteger ai = new atomiclntcger (0);private long starttime;public void init() starttime = system nemo time ();/* 使用 atomiclnteger. getandlncrement,测试结果为 1. 8 比 1. 7 有明 显性能提升* rcturn*/ private final int getandlncreasea () ini resul t 二 ai

7、. getandtncremenl(); if (result = test_size) system.out printin(system nanotimc() 一 starttime);system. exit(0);return result; /*差别* return*/ privatc final int getandincrcascb() int result; synchronized (this) resuit 二 n+;if (result 二二 test_stze) sys tcni. out. println (sys tcm. nano time ()- startti

8、me);system, exit (0);return result;/*使用atomiclnteger. compareandset在java代码层面做失败重试 (与 1. 7 的 atomiclnteger. getandtncrement 的实现类似),*测试结果为1. 7和1. 8几乎无性能差别* return*/ private final int getandincreasec() int result;do result = ai> get (); while (!ai. compareandset(result, result + 1); if (result 二二 te

9、st_size) sys tem. out. pri nt in (sys tem. nanotime () - starttime);system, exit (0);return result;public class mytask implements runnable ©override public void run() cdl. count down (); try cdl. await (); catch (interruptedexception e) e. printstacktrace ();while (true)getandlncreasea();/ geta

10、ndlncreasee();public static void main(string args) throws interruptedexception atomictest at 二 new atomictest ();for (int n 二 0; n thread_count; n+)new thread (at new mytask () start(); system, out. printin("start");at. init ();at. cdl. count down ();以下是在 intel (r) core (tm) i7-4710hq cpu

11、2. 50ghz (四核八线程)下的测 试结果(波动较小,所以每项只测试了四五次,取其中一个较中间的值): jdkl.7atomiclnteger. getandlncrement 12, 653, 757, 034synchronized 4,146,813, 462atomiclnteger. compareandset 12,952,821,234jdkl.8atomiclnteger. getandlncrement 2,159,486,620synchronized 4,067, 309, 911atomiclnteger. compareandset 12,893,18&

12、541补充:应网友要求,在此提供unsafe. getandaddlnt的和关源码以及我的测试代 码。用jad反编译jdkl. 8中unsafe得到的源码:public final int gctandaddlnt(object obj, long 1, int i) int j;doj 二 gettntvolati1e (obj, 1);while(icompareandswapint(obj, 1, j, j + i); return j;public native int getlntvolat订e(object obj, long 1);public final native bool

13、ean compareandswaplnt (object obj, long 1, int i, int j);openjdk8 的 unsafe 源码:public final int getandaddtnt(object o, long offset, int delta) int v;do v = getlntvolatile(o, offset); whi1e (!compareandswapint(o, offset, v, v + delta); return v;public native int getlntvolatile(object o, long offset);p

14、ublic final native boolean compareandswaplnt (object o, long offset, int expected, int x);我的测试代码(提示:如杲eclipse等ide报错,那是因为使用了受限的unsafe, 可以将警告级别从error降为warning,具体百度即可): import sun. misc. unsafe;public class atomictest private unsafe unsafe;private long valueoffset; public atomictest() field f;try f = u

15、nsafe, class. getdeclaredfield (,ztheunsafe,z); f.setaccessible (true);unsafe 二(unsafe)f. get(null);valueoffset =unsafe. objectfieldoffset (atomicinteger. class. getdeclaredfield (z,valuez, );catch(nosuchfieldexception e) private final int gctanclincrcascdo int result;doresul t = unsafe, getintvolat

16、ile(ai,valueoffset);while(! unsafe compareandswapjlnt (ai, valueoffset, result, result+1);if (result 二二 max) sys tom. out. pri ntl n(sys tcm. nanotimc ()s tart time);system. exit (0);return result;补充2:对于性能提升的原因,有以下推论,虽不敢说百分z百止确(因为没有 用jvm的源码作为论据),但还是有很大把握的,感谢网友周 可人和 liuxinglanyue!unsafe是经过特殊处理的,不能理解成常规的javei代码,区别在于: 在调用getandaddlnt的时候,如果系统底层支持fetch-and-add,那么它执行 的就是native方法,使用的是fetch-and-add;如果不支持,就按照上面的所看到的getandaddlnt方法体那样,以java代码的 方式去执行,使用的是compare-and-swap;这也止好跟opcnjdk8中unsafe:getandaddlnt上方的注释相吻合:/ the following contain cas-based java implementa

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论