@Contended和伪共享

原文: http://robsjava.blogspot.com/2014/03/what-is-false-sharing.html

Java8引入了@Contented这个新的注解来减少伪共享(False Sharing)的发生。本文介绍了@Contented注解并解释了为什么False Sharing是如何影响性能的。

缓存行

CPU读取内存数据时并非一次只读一个字节,而是会读一段64字节长度的连续的内存块(chunks of memory),这些块我们称之为缓存行(Cache line)。

假设你有两个线程(Thread1和Thread2)都会修改同一个volatile变量x:

1
volatile long x;

如果Thread1先改变x的值,然后Thread2又去读它:

1
2
Thread 1: x=3;
Thread 2: System.out.print(x);

那么x所在缓存行上的所有64个字节的值都要被重新加载,因为CPU核心间交换数据是以缓存行为最小单位的。当然Thread1和Thread2是有可能在同一个核心上运行的,但我们此处假设两个线程在不同的核心上运行。

已知long类型占8个字节,缓存行长度为64个字节,那么一个缓存行可以保存8个long型变量,我们已经有了一个long型的x,假设x所在缓存行里还有其他7个long型变量,v1到v7:

1
x, v1, v2, v3, v4, v5 ,v6 ,v7

伪共享(False Sharing)

这个缓存行可以被许多线程访问。如果其中一个修改了v2,那么会导致Thread1和Thread2都会重新加载整个缓存行。你可能会疑惑为什么修改了v2会导致Thread1和Thread2重新加载该缓存行,毕竟只是修改了v2的值啊。虽然说这些修改逻辑上是互相独立的,但同一缓存行上的数据是统一维护的,一致性的粒度并非体现在单个元素上。这种不必要的数据共享就称之为“伪共享”(False Sharing)。

填充(Padding)

一个CPU核心在加载一个缓存行时要执行上百条指令。如果一个核心要等待另外一个核心来重新加载缓存行,那么他就必须等在那里,称之为stall(停止运转)。减少伪共享也就意味着减少了stall的发生,其中一个手段就是通过填充(Padding)数据的形式,来保证本应有可能位于同一个缓存行的两个变量,在被多线程访问时必定位于不同的缓存行。

在下面这个例子里,我们试图通过填充的方式,使得xv1位于不同的缓存行:

1
2
3
4
5
6
7
8
9
10
11
public class FalseSharingWithPadding {
public volatile long x;
public volatile long p2; // padding
public volatile long p3; // padding
public volatile long p4; // padding
public volatile long p5; // padding
public volatile long p6; // padding
public volatile long p7; // padding
public volatile long p8; // padding
public volatile long v1;
}

在你考虑使用填充之前,必须要了解的一点是JVM可能会清除无用字段或重排无用字段的位置,这样的话,可能无形中又会引入伪共享。我们也没有办法指定对象在堆内驻留的位置。

为了避免无用字段被消除,通常我们会用volatile修饰一下。个人建议只需为处于激烈竞争状态的类进行填充处理,而且一般只有通过对其性能分析才能发现性能上的不同。通常在性能分析时,最好在对其迭代访问10000次之后再去采样,这样可以消除JVM本身的运行时优化策略带来的影响。

Java8和@Contended

除了对字段进行填充之外,还有一个比较清爽的方法,那就是对需要避免陷入伪共享的字段进行注解,这个注解暗示JVM应当将字段放入不同的缓存行,这也正是JEP142的相关内容。

该JEP引入了@Contented注解。被这个注解修饰的字段应当和其他的字段驻留在不同的位置。

1
2
3
4
5
public class Point {
int x;
@Contended
int y;
}

上面的代码将x和y置于不同的缓存行。@Contented注解将y移动到远离对象头部的地方,(以避免和x一起被加载到同一个缓存行)。

参考

http://openjdk.java.net/projects/jdk8/features
http://beautynbits.blogspot.co.uk/2012/11/the-end-for-false-sharing-in-java.html
http://openjdk.java.net/jeps/142
http://mechanical-sympathy.blogspot.co.uk/2011/08/false-sharing-java-7.html
http://stackoverflow.com/questions/19892322/when-will-jvm-use-intrinsics
https://blogs.oracle.com/dave/entry/java_contented_annotation_to_help

@Contended padding 伪共享相关推荐

  1. Java8中@Contended和伪共享

    @Contended和伪共享 原文:http://jingege.me/2016/05/31/sharing-false-and-contented/ 原文: http://robsjava.blog ...

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

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

  3. Java8中@Contended和伪共享 进行缓存行填充

    Java8引入了@Contented这个新的注解来减少伪共享(False Sharing)的发生.本文介绍了@Contented注解并解释了为什么False Sharing是如何影响性能的. 缓存行 ...

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

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

  5. Java8中用sun.misc.Contended避免伪共享(false sharing)

    转自:http://budairenqin.iteye.com/blog/2048257 关于伪共享这个概念,请先参照http://ifeve.com/falsesharing/ 伪共享的样子: Ja ...

  6. 性能优化之@Contended减少伪共享

    作者: 西魏陶渊明 博客: https://blog.springlearn.cn/ 西魏陶渊明 莫笑少年江湖梦,谁不少年梦江湖 一.什么叫伪共享 说到伪共享,就要说CPU缓存,我们程序执行时候信息会 ...

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

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

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

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

  9. Random(二)什么是伪共享?@sun.misc.Contended注解

    目录 1.背景简介 2.伪共享问题 3.问题解决 4.JDK使用示例 1.背景简介 我们知道,CPU 是不能直接访问内存的,数据都是从高速缓存中加载到寄存器的,高速缓存又有 L1,L2,L3 等层级. ...

最新文章

  1. 一种准标准CSV格式的介绍和分析以及解析算法
  2. 运维基础(2)实用工具篇
  3. SAP Spartacus B2B Org Unit树状结构的ghost数据
  4. java循环一年月份天数和_javawhile循环编写输入某年某月某日,判断这一天是这一年的第几…...
  5. sql空字符串判断函数_access常用的内置函数
  6. linux下 如何用信号signal 终止或者暂停子线程,linux下实现线程暂停
  7. php源码安装配置,php源码安装时configure配置参数 | 学步园
  8. 汇编语言:实验7寻址方式在结构化数据访问中的应用
  9. 特斯拉Cybertruck与新款Model S同时在加州工厂曝光
  10. iPhone 13 的十大爆料:“十三”到底“香不香”?
  11. ImportError: cannot import name ‘XGBClassifier‘
  12. 《Head first HTML与CSS 第二版》读书笔记 第一章 了解HTML
  13. 1024,今天给大家发100个现金红包和思否课程、掘金小册
  14. JDK8的下载,安装和配置
  15. 超干货|城市信息模型介绍CIM1-CIM7级
  16. 数字孪生|数字孪生装备-关键技术和发展阶段
  17. 用计算机房的英语造句简单,用英语造句子elder.doc
  18. 深造分布式 打败面试官 招式二 新手上路
  19. VLAN基础VLAN间路由联动OSPF实验
  20. Android EventBus使用

热门文章

  1. 图像处理:Python代码计算图像对比度
  2. matlab结构体数组定义方法
  3. 读Hean first jQuery笔记1(基础)
  4. WiFi Analyer
  5. asterisk 数据库 php,使用FreePBX和Asterisk调用PHP脚本
  6. 【全奖博士生】悉尼科技大学ReLER实验室招收CV/AI方向
  7. 一句话让你记住美国的各个州
  8. 30岁女生给20岁女生的建议,最后一条最重要
  9. 诱骗取电芯片XSQ10让QC协议/华为SCP快充输出9V12V
  10. Swagger UI 3.0 404 错误