Java8中用sun.misc.Contended避免伪共享(false sharing)
转自:http://budairenqin.iteye.com/blog/2048257
关于伪共享这个概念,请先参照http://ifeve.com/falsesharing/
伪共享的样子:
![](http://budairenqin.iteye.com/images/icon_star.png)
- Java view:
- public class VolatileLong {
- volatile long v = 0L;
- }
- Memory view:
- ...–––-)(––––HV––––HV–––)(–––...
我们看到,两个VolatileLong对象被load到了同一个缓存行里面,如果一个线程要修改对象1,另一个线程同时要修改对象2,此时就要面对伪共享这个无形的性能杀手了
jdk6中的解决办法:
![](http://budairenqin.iteye.com/images/icon_star.png)
- 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的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
![](http://budairenqin.iteye.com/images/icon_star.png)
- 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的地方:
![](http://budairenqin.iteye.com/images/icon_star.png)
- 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")
最后,贴上测试代码,感兴趣的各自测试吧
![](http://budairenqin.iteye.com/images/icon_star.png)
- 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;
- }
- }
我机器上的测试结果:
![](http://budairenqin.iteye.com/images/icon_star.png)
- VolatileLong: duration = 29594765000
- VolatileLong2:duration = 7234555000
- VolatileLong3:duration = 7167475000
测试代码来自 http://ifeve.com/falsesharing/ ,稍有改动
Java8中用sun.misc.Contended避免伪共享(false sharing)相关推荐
- @sun.misc.Contended避免伪共享(false sharing)
转载自:http://www.myexception.cn/program/1630142.html Java8中使用sun.misc.Contended注解来避免伪共享(false sharing) ...
- @sun.misc.Contended 解决伪共享问题
先来看下什么叫做伪共享,转载自并发编程网 – ifeve.com 链接地址: 伪共享(False Sharing) 缓存系统中是以缓存行(cache line)为单位存储的.缓存行是2的整数幂个连续字 ...
- 什么是伪共享?Java8如何使用@sun.misc.Contended避免伪共享?
什么是伪共享 缓存系统中是以缓存行(cache line)为单位存储的.缓存行是2的整数幂个连续字节,一般为32-256个字节.最常见的缓存行大小是64个字节.当多线程修改互相独立的变量时,如果这些变 ...
- 聊聊java8中的@sun.misc.Contended与伪共享
"持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情" @[toc] 在前面学习ConcurrentHashMap的size方法的过程中 ...
- Java8的@sun.misc.Contended注解
@sun.misc.Contended 介绍 @sun.misc.Contended 是 Java 8 新增的一个注解,对某字段加上该注解则表示该字段会单独占用一个缓存行(Cache Line). 这 ...
- Java8的@sun.misc.Contended注解解决伪共享问题
本文源自转载:Java8的@sun.misc.Contended注解 目录 一.@sun.misc.Contended 介绍 二.单独使用一个缓存行有什么作用--避免伪共享 三.@sun.misc.C ...
- 从缓存行出发理解volatile变量、伪共享False sharing、disruptor
volatile关键字 当变量被某个线程A修改值之后,其它线程比如B若读取此变量的话,立刻可以看到原来线程A修改后的值 注:普通变量与volatile变量的区别是volatile的特殊规则保证了新值能 ...
- 伪共享(False Sharing)
原文地址:http://ifeve.com/false-sharing/ 作者:Martin Thompson 译者:丁一 缓存系统中是以缓存行(cache line)为单位存储的.缓存行是2的整数 ...
- 从Java视角理解伪共享(False Sharing)
从我的前一篇博文中, 我们知道了CPU缓存及缓存行的概念, 同时用一个例子说明了编写单线程Java代码时应该注意的问题. 下面我们讨论更为复杂, 而且更符合现实情况的多核编程时将会碰到的问题. 这些问 ...
最新文章
- linux+swig+python,linux下使用swig让python调用C++(复杂版:包括多文件调用和链接库)...
- Java基础篇:JDBC核心技术
- CentOS 7 学习(一) 配置LAMP和Nginx
- JS-排序详解:冒泡排序、选择排序和快速排序
- als算法参数_Spark2.0协同过滤与ALS算法介绍
- linux安装Python36
- 如何看Cortex-M系列处理器差异与共性?技术老司机Joseph带你飞
- Educational Codeforces Round 114 (Rated for Div. 2) D. The Strongest Build 暴力 + bfs
- zabbix server 迁移步骤
- Python模拟登录实战,采集整站表格数据
- 上海 · 百度语义分割Pro沙龙,高性能深度学习实战营
- 修改linq结果集_linq 查询的结果会开辟新的内存吗?
- 相反数-网易校招编程题
- matlab实现序列卷积和运算,用matlab计算序列卷积和并绘图
- 【阿里云镜像】切换阿里巴巴开源镜像站镜像——Kali镜像
- 剪刀石头布(你出一个版)
- 忘记开机密码怎么开机
- VTK重建CT图像,写入和读取STL格式文件
- zend optimizer php5.5,zend guard5.5版本下载-zend guard php5.5v5.5 免费版 - 极光下载站
- 基于ESP32-CAM 和 OpenCV 设计的手势控制虚拟鼠标