- 浏览: 199304 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
budairenqin:
budairenqin 写道carlosfu 写道膜拜一下,要 ...
写个RPC娱乐一下 -
budairenqin:
carlosfu 写道膜拜一下,要是把实现过程写个博客或者文档 ...
写个RPC娱乐一下 -
dengchang1:
好文章。 详细看了《Netty源码细节1--IO线程(Even ...
Netty源码细节3--accept(Linux os层 + Netty层代码细节) -
carlosfu:
膜拜一下,要是把实现过程写个博客或者文档就更赞了
写个RPC娱乐一下 -
budairenqin:
I_am_rookie 写道你好!能把安装包发我一下吗?我找了 ...
CentOS 6.3 X86_64安装MySQL 5.5.28 64-Bit RPM以及my.cnf配置
Java8中用sun.misc.Contended避免伪共享(false sharing)
关于伪共享这个概念,请先参照http://ifeve.com/falsesharing/
伪共享的样子:
我们看到,两个VolatileLong对象被load到了同一个缓存行里面,如果一个线程要修改对象1,另一个线程同时要修改对象2,此时就要面对伪共享这个无形的性能杀手了
jdk6中的解决办法:
很多大神的代码都是通过上面的方式也就是long padding来避免伪共享
例如:
1.Doug Lea的jsr166中早期的LinkedTransferQueue版本http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166y/LinkedTransferQueue.java?revision=1.1&view=markup
2.还是Doug Lea的ConcurrentHashMapV8http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/ConcurrentHashMapV8.java?revision=1.121&view=markup(在java8中的版本已经用sun.misc.Contended替换long padding)
3.大名鼎鼎的无锁并发框架Disruptor https://github.com/LMAX-Exchange/disruptor
4.等等等...
long padding的解决办法不怎么优雅,并且在jdk7某个版本以后能会优化掉long padding,尼玛java程序员是有多难啊,想尽了一切办法对付jdk7中的这个优化,详情点击http://ifeve.com/false-sharing-java-7/
但是但是...开始使用jdk8的同学注意了,java8已经给出了官方的解决办法...
就是sun.misc.Contended注解http://mail.openjdk.java.net/pipermail/hotspot-dev/2012-November/007309.html
要注意的是user classpath使用此注解默认是无效的,需要在jvm启动时设置-XX:-RestrictContended
jdk8中已经使用sun.misc.Contended的地方:
最后,贴上测试代码,感兴趣的各自测试吧
我机器上的测试结果:
测试代码来自http://ifeve.com/falsesharing/,稍有改动
是15*8,因为用7个下标保证了会有56个字节填充在数值的任何一边,56字节的填充+8字节的long数值正好装进一行64字节的缓存行。
伪共享的样子:
Java view: public class VolatileLong { volatile long v = 0L; } Memory view: ...–––-)(––––HV––––HV–––)(–––...
我们看到,两个VolatileLong对象被load到了同一个缓存行里面,如果一个线程要修改对象1,另一个线程同时要修改对象2,此时就要面对伪共享这个无形的性能杀手了
jdk6中的解决办法:
Java view: public class VolatileLong { volatile long p0, p1, p2, p3, p4, p5, p6; volatile long v = 0L; volatile long q0, q1, q2, q3, q4, q5, q6; } Memory view: ...–––-)(ppppppHVqqqqqq)(–––...
很多大神的代码都是通过上面的方式也就是long padding来避免伪共享
例如:
1.Doug Lea的jsr166中早期的LinkedTransferQueue版本http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166y/LinkedTransferQueue.java?revision=1.1&view=markup
2.还是Doug Lea的ConcurrentHashMapV8http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/ConcurrentHashMapV8.java?revision=1.121&view=markup(在java8中的版本已经用sun.misc.Contended替换long padding)
3.大名鼎鼎的无锁并发框架Disruptor https://github.com/LMAX-Exchange/disruptor
4.等等等...
long padding的解决办法不怎么优雅,并且在jdk7某个版本以后能会优化掉long padding,尼玛java程序员是有多难啊,想尽了一切办法对付jdk7中的这个优化,详情点击http://ifeve.com/false-sharing-java-7/
但是但是...开始使用jdk8的同学注意了,java8已经给出了官方的解决办法...
就是sun.misc.Contended注解http://mail.openjdk.java.net/pipermail/hotspot-dev/2012-November/007309.html
Java view: // jdk8新特性,Contended注解避免false sharing // Restricted on user classpath // Unlock: -XX:-RestrictContended @sun.misc.Contended public class VolatileLong { volatile long v = 0L; } Memory view: ...–––-)(******HV******)(–––...
要注意的是user classpath使用此注解默认是无效的,需要在jvm启动时设置-XX:-RestrictContended
jdk8中已经使用sun.misc.Contended的地方:
src/share/classes/java/util/concurrent/ConcurrentHashMap.java 2458: @sun.misc.Contended static final class CounterCell { src/share/classes/java/util/concurrent/Exchanger.java 310: * bookkeeping. Padded via @sun.misc.Contended to reduce m 313: @sun.misc.Contended static final class Node { src/share/classes/java/util/concurrent/ForkJoinPool.java 161:@sun.misc.Contended 643: @sun.misc.Contended src/share/classes/java/util/concurrent/atomic/Striped64.java 55: * (via @sun.misc.Contended) to reduce cache contention. Pa 119: @sun.misc.Contended static final class Cell { src/share/classes/java/lang/Thread.java 2004: @sun.misc.Contended("tlr") 2008: @sun.misc.Contended("tlr") 2012: @sun.misc.Contended("tlr")
最后,贴上测试代码,感兴趣的各自测试吧
public class FalseSharing implements Runnable { public final static int NUM_THREADS = 4; // change public final static long ITERATIONS = 500L * 1000L * 1000L; private final int arrayIndex; private static VolatileLong3[] longs = new VolatileLong3[NUM_THREADS]; static { for (int i = 0; i < longs.length; i++) { longs[i] = new VolatileLong3(); } } public FalseSharing(final int arrayIndex) { this.arrayIndex = arrayIndex; } public static void main(final String[] args) throws Exception { long start = System.nanoTime(); runTest(); System.out.println("duration = " + (System.nanoTime() - start)); } private static void runTest() throws InterruptedException { Thread[] threads = new Thread[NUM_THREADS]; for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(new FalseSharing(i)); } for (Thread t : threads) { t.start(); } for (Thread t : threads) { t.join(); } } public void run() { long i = ITERATIONS + 1; while (0 != --i) { longs[arrayIndex].value = i; } } public final static class VolatileLong { public volatile long value = 0L; } // long padding避免false sharing // 按理说jdk7以后long padding应该被优化掉了,但是从测试结果看padding仍然起作用 public final static class VolatileLong2 { volatile long p0, p1, p2, p3, p4, p5, p6; public volatile long value = 0L; volatile long q0, q1, q2, q3, q4, q5, q6; } // jdk8新特性,Contended注解避免false sharing // Restricted on user classpath // Unlock: -XX:-RestrictContended @sun.misc.Contended public final static class VolatileLong3 { public volatile long value = 0L; } }
我机器上的测试结果:
VolatileLong: duration = 29594765000 VolatileLong2:duration = 7234555000 VolatileLong3:duration = 7167475000
测试代码来自http://ifeve.com/falsesharing/,稍有改动
评论
2 楼
budairenqin
2014-09-15
liuInsect 写道
volatile long p0, p1, p2, p3, p4, p5, p6;
public volatile long value = 0L;
volatile long q0, q1, q2, q3, q4, q5, q6;
这里 为什么是 13 * 8 个字节 还不是 (7+1)*8? 8*8 =64不是正好是一个cache line么?
public volatile long value = 0L;
volatile long q0, q1, q2, q3, q4, q5, q6;
这里 为什么是 13 * 8 个字节 还不是 (7+1)*8? 8*8 =64不是正好是一个cache line么?
是15*8,因为用7个下标保证了会有56个字节填充在数值的任何一边,56字节的填充+8字节的long数值正好装进一行64字节的缓存行。
1 楼
liuInsect
2014-05-21
volatile long p0, p1, p2, p3, p4, p5, p6;
public volatile long value = 0L;
volatile long q0, q1, q2, q3, q4, q5, q6;
这里 为什么是 13 * 8 个字节 还不是 (7+1)*8? 8*8 =64不是正好是一个cache line么?
public volatile long value = 0L;
volatile long q0, q1, q2, q3, q4, q5, q6;
这里 为什么是 13 * 8 个字节 还不是 (7+1)*8? 8*8 =64不是正好是一个cache line么?
发表评论
-
JUC中Atomic class之lazySet的一点疑惑
2015-11-15 20:45 913发在并发编程网了 http://ifeve.com/juc-a ... -
JUC中Atomic class之lazySet的一点疑惑
2015-06-19 01:27 0最近再次翻netty和disrupt的源码, 发现一些地方使用 ... -
Java8 中HashMap的优化
2014-04-25 11:35 5914先看代码,来自HashMap.putVal() ... -
Java 绕过编译器检查抛出“受检查的”异常
2014-01-23 16:45 2236个别特殊情况下,我们 ... -
java 在toString()方法中修改对象状态导致诡异的debug问题
2013-06-03 17:06 1593protected char buffer[]; . ... -
Java并发系列
2013-02-11 19:54 518收藏下自己读过的并发系列的好文章,做个目录方便自己重温,不断更 ... -
远程执行小工具
2013-02-04 23:49 2500今天想给项目写个远程执行的小工具 1.客户端动态编译要远 ... -
支持并发的结果缓存
2013-01-22 17:41 380改自《Java Concurrency in Pr ... -
Java字节码框架asm快速入门
2013-01-16 21:03 8209asm是一个java的字节码 ... -
一个基于JDBC的MySql数据迁移工具类
2013-01-03 18:14 540没有什么参考性,大概只适合我当前的场景: 1.数据源为一个,目 ... -
启动java的shell脚本
2013-02-19 23:38 1296一个netty tcp长连接的项目中用到的启动脚本(脚本非原创 ... -
模仿ConcurrentHashMap
2012-12-16 19:09 0import java.io.Serializable ... -
运行时(at runtime)找到Class对象的classfile location
2012-08-29 23:42 1221以下代码参考 http://www.javaworld.com ... -
Web应用下JVM从哪个类包加载指定类
2012-08-29 22:50 0以下内容来自《Spring3.x企业应用开发实战》一书,收藏下 ... -
Java虚拟机指令操作码助记符
2012-06-21 17:36 2547以下内容均来自IcyFenix等大牛翻译的Java虚拟机规范 ... -
JSR 292 的用法 (MethodHandle...)
2012-02-05 19:45 514用例转自:http://code.google.com/p/j ... -
System.getProperty() 参数大全
2011-12-09 11:28 1741import java.util.Enumeration; ... -
自定义的类装载器-从DB装载class(附上对类装载器的分析)
2011-11-25 14:31 412代码才是最实在的,先从代码开始,然后再一步一步分析: 第一步: ... -
java安全管理器-SecurityManager
2011-11-23 15:16 3403当java应用程序启动时,它还没有安全管理器,应用程序可以通过 ... -
jvm学习笔记-class文件检验器
2011-11-23 03:33 410唉,记忆力衰退了吗? ...
相关推荐
sun.misc.BASE64Decoder 其中包括 Android Base64Jar包 以及Java源代码 sun.misc.BASE64Decoder 其中包括 Android Base64Jar包 以及Java源代码 sun.misc.BASE64Decoder 其中包括 Android Base64Jar包 以及...
java开发 sun.misc.BASE64Decoder.jar包下载 java开发 sun.misc.BASE64Decoder.jar包下载
冲浪后发现JDK中的lib\tools.jar和JRE中的lib\rt.jar已从Java SE 9中删除,也就是1.8版本后的jdk已经不再支持sun.misc.BASE64Decoder和sun.misc.BASE64Encoder。 这些JAR中可用的类和资源现在以文件中的内部格式存储...
在MyEclipse中编写Java代码时,用到了BASE64Decoder,import sun.misc.BASE64Decoder;可是Eclipse提示: Access restriction: The type BASE64Decoder is not accessible due to restriction on required library...
sun.misc.BASE64Decoder.jar 绿色版 官方版本自己打包好的,可以直接调用,欢迎下载
JDK8中sun.misc包下的UnSafe类,想查看源码的就拿走,没积分的请与我联系!xtfggef@gmail.com
RSA算法加密解密JAVA实现跟现实加密串的sun.misc.BASE64Decoder.jar
sun.misc.BASE64Encoder源码及jar包
安装了JDK 9以上版本,发现sun.misc.Base64Encoder和sun.misc.Base64Decoder无法使用。找不到导入的包此时将下面的包导入libs中就可以了
sun.misc.BASE64Decoder.jar sun.misc.BASE64Decoder.jar sun.misc.BASE64Decoder.jar sun.misc.BASE64Decoder.jar
如名,就是java 的sun.misc.BASE64Decoder.jar 包。 其实是已经过时的东西,因为java8推出了新的库来替代它,且android也有内置的base64相关的工具库。 但是,总有一些工程是要用老库的,也没办法(懒或者烦)更新...
sun.misc.BASEDecoder、sun.misc.BASEEncoder等 在编码解码是用到的工具类,导入jar包之后,就可以正常使用此类
sun.misc.BASE64Encoder找不到jar包,就导入sun.misc.BASE64Decoder.jar 封装好的jar包,无需再导入jre系统库了
Base64算法的加密解密都是使用sun.misc包下的BASE64Encoder及BASE64Decoder来进行的,例如Base64 和 Base64URL等需要依赖它
1.包含 sun.misc.BASE64加解密源码和jar【源码仅仅几个类而已】 2.完整的sun.misc.BASE64类【直接项目引用即可】
找不到sun.misc.BASE64Encoder 时,导入bcprov-ext-jdk15on-149.jar包就行
JDK8中sun.misc下UnSafe类源代码 UnSafe.java JDK8中sun.misc下UnSafe类源代码 UnSafe.java
放心下载
apache-commons-codec-1.4.jar和sun.misc.BASE64Encoder.jar和sun.misc.BASE64Decoder.jar
解决android无法使用sun.misc.CharacterDecoder,添加了rt.jar也不行。 然后本人就寻找了其六个java源文件,添加到项目中使用即可。 BASE64Decoder.java BASE64Encoder.java CEFormatException.java ...