转自:http://budairenqin.iteye.com/blog/2048257

关于伪共享这个概念,请先参照http://ifeve.com/falsesharing/

伪共享的样子:

Java代码  
  1. Java view:
  2. public class VolatileLong {
  3. volatile long v = 0L;
  4. }
  5. Memory view:
  6. ...–––-)(––––HV––––HV–––)(–––...

我们看到,两个VolatileLong对象被load到了同一个缓存行里面,如果一个线程要修改对象1,另一个线程同时要修改对象2,此时就要面对伪共享这个无形的性能杀手了

jdk6中的解决办法:

Java代码  
  1. Java view:
  2. public class VolatileLong {
  3. volatile long p0, p1, p2, p3, p4, p5, p6;
  4. volatile long v = 0L;
  5. volatile long q0, q1, q2, q3, q4, q5, q6;
  6. }
  7. Memory view:
  8. ...–––-)(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的ConcurrentHashMapV8 http://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代码  
  1. Java view:
  2. // jdk8新特性,Contended注解避免false sharing
  3. // Restricted on user classpath
  4. // Unlock: -XX:-RestrictContended
  5. @sun.misc.Contended
  6. public class VolatileLong {
  7. volatile long v = 0L;
  8. }
  9. Memory view:
  10. ...–––-)(******HV******)(–––...

要注意的是user classpath使用此注解默认是无效的,需要在jvm启动时设置-XX:-RestrictContended

jdk8中已经使用sun.misc.Contended的地方:

Java代码  
  1. src/share/classes/java/util/concurrent/ConcurrentHashMap.java
  2. 2458: @sun.misc.Contended static final class CounterCell {
  3. src/share/classes/java/util/concurrent/Exchanger.java
  4. 310: * bookkeeping. Padded via @sun.misc.Contended to reduce m
  5. 313: @sun.misc.Contended static final class Node {
  6. src/share/classes/java/util/concurrent/ForkJoinPool.java 161:@sun.misc.Contended
  7. 643: @sun.misc.Contended
  8. src/share/classes/java/util/concurrent/atomic/Striped64.java
  9. 55: * (via @sun.misc.Contended) to reduce cache contention. Pa
  10. 119: @sun.misc.Contended static final class Cell {
  11. src/share/classes/java/lang/Thread.java
  12. 2004: @sun.misc.Contended("tlr")
  13. 2008: @sun.misc.Contended("tlr")
  14. 2012: @sun.misc.Contended("tlr")

最后,贴上测试代码,感兴趣的各自测试吧

Java代码  
  1. public class FalseSharing implements Runnable {
  2. public final static int NUM_THREADS = 4; // change
  3. public final static long ITERATIONS = 500L * 1000L * 1000L;
  4. private final int arrayIndex;
  5. private static VolatileLong3[] longs = new VolatileLong3[NUM_THREADS];
  6. static {
  7. for (int i = 0; i < longs.length; i++) {
  8. longs[i] = new VolatileLong3();
  9. }
  10. }
  11. public FalseSharing(final int arrayIndex) {
  12. this.arrayIndex = arrayIndex;
  13. }
  14. public static void main(final String[] args) throws Exception {
  15. long start = System.nanoTime();
  16. runTest();
  17. System.out.println("duration = " + (System.nanoTime() - start));
  18. }
  19. private static void runTest() throws InterruptedException {
  20. Thread[] threads = new Thread[NUM_THREADS];
  21. for (int i = 0; i < threads.length; i++) {
  22. threads[i] = new Thread(new FalseSharing(i));
  23. }
  24. for (Thread t : threads) {
  25. t.start();
  26. }
  27. for (Thread t : threads) {
  28. t.join();
  29. }
  30. }
  31. public void run() {
  32. long i = ITERATIONS + 1;
  33. while (0 != --i) {
  34. longs[arrayIndex].value = i;
  35. }
  36. }
  37. public final static class VolatileLong {
  38. public volatile long value = 0L;
  39. }
  40. // long padding避免false sharing
  41. // 按理说jdk7以后long padding应该被优化掉了,但是从测试结果看padding仍然起作用
  42. public final static class VolatileLong2 {
  43. volatile long p0, p1, p2, p3, p4, p5, p6;
  44. public volatile long value = 0L;
  45. volatile long q0, q1, q2, q3, q4, q5, q6;
  46. }
  47. // jdk8新特性,Contended注解避免false sharing
  48. // Restricted on user classpath
  49. // Unlock: -XX:-RestrictContended
  50. @sun.misc.Contended
  51. public final static class VolatileLong3 {
  52. public volatile long value = 0L;
  53. }
  54. }

我机器上的测试结果:

Java代码  
  1. VolatileLong: duration = 29594765000
  2. VolatileLong2:duration = 7234555000
  3. VolatileLong3:duration = 7167475000

测试代码来自 http://ifeve.com/falsesharing/ ,稍有改动

Java8中用sun.misc.Contended避免伪共享(false sharing)相关推荐

  1. @sun.misc.Contended避免伪共享(false sharing)

    转载自:http://www.myexception.cn/program/1630142.html Java8中使用sun.misc.Contended注解来避免伪共享(false sharing) ...

  2. @sun.misc.Contended 解决伪共享问题

    先来看下什么叫做伪共享,转载自并发编程网 – ifeve.com 链接地址: 伪共享(False Sharing) 缓存系统中是以缓存行(cache line)为单位存储的.缓存行是2的整数幂个连续字 ...

  3. 什么是伪共享?Java8如何使用@sun.misc.Contended避免伪共享?

    什么是伪共享 缓存系统中是以缓存行(cache line)为单位存储的.缓存行是2的整数幂个连续字节,一般为32-256个字节.最常见的缓存行大小是64个字节.当多线程修改互相独立的变量时,如果这些变 ...

  4. 聊聊java8中的@sun.misc.Contended与伪共享

    "持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情" @[toc] 在前面学习ConcurrentHashMap的size方法的过程中 ...

  5. Java8的@sun.misc.Contended注解

    @sun.misc.Contended 介绍 @sun.misc.Contended 是 Java 8 新增的一个注解,对某字段加上该注解则表示该字段会单独占用一个缓存行(Cache Line). 这 ...

  6. Java8的@sun.misc.Contended注解解决伪共享问题

    本文源自转载:Java8的@sun.misc.Contended注解 目录 一.@sun.misc.Contended 介绍 二.单独使用一个缓存行有什么作用--避免伪共享 三.@sun.misc.C ...

  7. 从缓存行出发理解volatile变量、伪共享False sharing、disruptor

    volatile关键字 当变量被某个线程A修改值之后,其它线程比如B若读取此变量的话,立刻可以看到原来线程A修改后的值 注:普通变量与volatile变量的区别是volatile的特殊规则保证了新值能 ...

  8. 伪共享(False Sharing)

    原文地址:http://ifeve.com/false-sharing/ 作者:Martin Thompson  译者:丁一 缓存系统中是以缓存行(cache line)为单位存储的.缓存行是2的整数 ...

  9. 从Java视角理解伪共享(False Sharing)

    从我的前一篇博文中, 我们知道了CPU缓存及缓存行的概念, 同时用一个例子说明了编写单线程Java代码时应该注意的问题. 下面我们讨论更为复杂, 而且更符合现实情况的多核编程时将会碰到的问题. 这些问 ...

最新文章

  1. linux+swig+python,linux下使用swig让python调用C++(复杂版:包括多文件调用和链接库)...
  2. Java基础篇:JDBC核心技术
  3. CentOS 7 学习(一) 配置LAMP和Nginx
  4. JS-排序详解:冒泡排序、选择排序和快速排序
  5. als算法参数_Spark2.0协同过滤与ALS算法介绍
  6. linux安装Python36
  7. 如何看Cortex-M系列处理器差异与共性?技术老司机Joseph带你飞
  8. Educational Codeforces Round 114 (Rated for Div. 2) D. The Strongest Build 暴力 + bfs
  9. zabbix server 迁移步骤
  10. Python模拟登录实战,采集整站表格数据
  11. 上海 · 百度语义分割Pro沙龙,高性能深度学习实战营
  12. 修改linq结果集_linq 查询的结果会开辟新的内存吗?
  13. 相反数-网易校招编程题
  14. matlab实现序列卷积和运算,用matlab计算序列卷积和并绘图
  15. 【阿里云镜像】切换阿里巴巴开源镜像站镜像——Kali镜像
  16. 剪刀石头布(你出一个版)
  17. 忘记开机密码怎么开机
  18. VTK重建CT图像,写入和读取STL格式文件
  19. zend optimizer php5.5,zend guard5.5版本下载-zend guard php5.5v5.5 免费版 - 极光下载站
  20. 基于ESP32-CAM 和 OpenCV 设计的手势控制虚拟鼠标

热门文章

  1. 分布式系统(数据复制与一致性)
  2. 117_qt制作mplayer音乐播放器,BUG总结
  3. NGINX轮询机制的几种形式
  4. ajax对数据进行封装,ajax封装
  5. c语言中获取当前时间的函数
  6. python 增加图像对比度
  7. jq 循环获取某class所有的attr里面的值
  8. 华为MateBook D笔记本(8代处理器)安装Win7系统
  9. 遗传算法求三元函数极值(python)-采用实数编码
  10. 搜书利器 -- 壹搜网