java中什么是 伪共享_【Java】聊聊多线程中的伪共享现象

首页

专栏

java

文章详情

0

聊聊多线程中的伪共享现象

109340.html小强大人发布于 1 月 27 日

什么是伪共享?

讲伪共享之前,让我们先乘坐时光机,回到大学课堂,来重温下计算机组成原理的基础知识。我们知道,CPU和内存的运行速度相差很大,为了解决这个问题,在CPU和内存之间会加一级或多级高速缓存(Cache)。这个Cache一般是集成在CPU内部的,所以也叫CPU Cache。下图是一个两级Cache的CPU-Cache-内存架构。

fb472a89582457dc9319c0b3bc2e2bcf.png

数据在Cache中是按行存储的,其中每一行称为一个Cache行,如下图所示。它是CPU与内存数据交换的基本单位。Cache行的大小一般为2的幂次字节数。

eb608aedde4f3405349e9fe46b480915.png

CPU-Cache-内存架构的工作原理是这样的:当CPU访问某个变量时,首先会从CPU Cache里查看是否有该变量,如果有直接获取并返回,否则从内存中获取,然后把该变量所在内存区域的一个Cache行大小的内存数据复制到Cache中,这就是我们所说的局部性原理。由于存放到Cache行的不是单个变量,而是一个内存块数据,所以会出现多个变量放在一个Cache行中。当多个线程同时修改同一个缓存行里面的不同变量时,由于同一时刻只允许一个线程操作缓存行,一个线程成功获取缓存行的修改权时,其他线程会互斥等待,并且由于缓存一致性协议,其他线程相应的缓存行会失效,需要重新从内存获取数据,这无疑耗费了更多时间。所以相比把每个变量放在不同的缓存行,性能反而有所下降,这就是伪共享现象。

如下图所示,变量x,y放在同一个缓存行中,线程1操作缓存行的x变量,线程2操作y变量。

76bb4eceae875ab7a1dd9872bb864b3c.png

如何避免伪共享呢?

在JDK1.8之前,通常是通过字节填充的方式。什么意思呢?就是用到一个变量时,补充额外的若干辅助变量,使得这些变量刚好填充满一个缓存行,这样就避免了多个变量存放在一个缓存行中。具体看下面示例代码:

static final class PaddedLongField {

public volatile long value = 0L;

public long p1,p2,p3,p4,p5,p6;

}

假如CPU Cache行大小为64字节,那么我们这里填充了6个long型的变量,每个long型变量占8个字节,加上value一共7*8=56字节,另外,别忘了PaddedLongField是一个类对象,对象头还要占用8个字节,所以一个PaddedLongField对象占用64个字节,刚好填充满一个缓存行。

在JDK1.8之后,提供了一个@sun.misc.Contended注解,用来解决伪共享问题。此时,我们上面的代码就可以简化了:

@sun.misc.Contended

static final class PaddedLongField {

public volatile long value = 0L;

}

@Contended注解不仅可以修饰类,也可以修饰变量:

2c5fd3d81e08943e658c409bf9936665.png

JUC源码里很多使用这个注解的,比如Thread类里threadLocalRandom相关的变量:

05a85b7c4ab00b3c0982ab31cc896cfb.png

再比如LongAdder内部用到的Cell也用了这个注解:

f754481e901017ff3fb3dd036033739c.png

再比如ForkJoinPool类上面也修饰了:

e1c5eb920ebc08bb9f397012c3168cc8.png

最后需要注意下,@Contended注解默认只用于Java核心类,比如rt.jar下的类。如果我们应用程序中想使用这个注解,需要添加一个JVM参数:-XX:-RestrictContended,填充的默认宽度为128字节,若需自定义宽度则可以用另一个参数:-XX:ContendedPaddingWidth=xxx

本文就到这里啦,若这篇文章对你有所帮助的话,点个赞再走叭!谢谢支持!

参考资料:

《Java并发编程之美》

java

阅读 53更新于 1 月 27 日

赞收藏

分享

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议

109340.html

小强大人

9声望

1粉丝

关注作者

0 条评论

得票时间

109340.html

提交评论

109340.html

小强大人

9声望

1粉丝

关注作者

宣传栏

什么是伪共享?

讲伪共享之前,让我们先乘坐时光机,回到大学课堂,来重温下计算机组成原理的基础知识。我们知道,CPU和内存的运行速度相差很大,为了解决这个问题,在CPU和内存之间会加一级或多级高速缓存(Cache)。这个Cache一般是集成在CPU内部的,所以也叫CPU Cache。下图是一个两级Cache的CPU-Cache-内存架构。

fb472a89582457dc9319c0b3bc2e2bcf.png

数据在Cache中是按行存储的,其中每一行称为一个Cache行,如下图所示。它是CPU与内存数据交换的基本单位。Cache行的大小一般为2的幂次字节数。

eb608aedde4f3405349e9fe46b480915.png

CPU-Cache-内存架构的工作原理是这样的:当CPU访问某个变量时,首先会从CPU Cache里查看是否有该变量,如果有直接获取并返回,否则从内存中获取,然后把该变量所在内存区域的一个Cache行大小的内存数据复制到Cache中,这就是我们所说的局部性原理。由于存放到Cache行的不是单个变量,而是一个内存块数据,所以会出现多个变量放在一个Cache行中。当多个线程同时修改同一个缓存行里面的不同变量时,由于同一时刻只允许一个线程操作缓存行,一个线程成功获取缓存行的修改权时,其他线程会互斥等待,并且由于缓存一致性协议,其他线程相应的缓存行会失效,需要重新从内存获取数据,这无疑耗费了更多时间。所以相比把每个变量放在不同的缓存行,性能反而有所下降,这就是伪共享现象。

如下图所示,变量x,y放在同一个缓存行中,线程1操作缓存行的x变量,线程2操作y变量。

76bb4eceae875ab7a1dd9872bb864b3c.png

如何避免伪共享呢?

在JDK1.8之前,通常是通过字节填充的方式。什么意思呢?就是用到一个变量时,补充额外的若干辅助变量,使得这些变量刚好填充满一个缓存行,这样就避免了多个变量存放在一个缓存行中。具体看下面示例代码:

static final class PaddedLongField {

public volatile long value = 0L;

public long p1,p2,p3,p4,p5,p6;

}

假如CPU Cache行大小为64字节,那么我们这里填充了6个long型的变量,每个long型变量占8个字节,加上value一共7*8=56字节,另外,别忘了PaddedLongField是一个类对象,对象头还要占用8个字节,所以一个PaddedLongField对象占用64个字节,刚好填充满一个缓存行。

在JDK1.8之后,提供了一个@sun.misc.Contended注解,用来解决伪共享问题。此时,我们上面的代码就可以简化了:

@sun.misc.Contended

static final class PaddedLongField {

public volatile long value = 0L;

}

@Contended注解不仅可以修饰类,也可以修饰变量:

2c5fd3d81e08943e658c409bf9936665.png

JUC源码里很多使用这个注解的,比如Thread类里threadLocalRandom相关的变量:

05a85b7c4ab00b3c0982ab31cc896cfb.png

再比如LongAdder内部用到的Cell也用了这个注解:

f754481e901017ff3fb3dd036033739c.png

再比如ForkJoinPool类上面也修饰了:

e1c5eb920ebc08bb9f397012c3168cc8.png

最后需要注意下,@Contended注解默认只用于Java核心类,比如rt.jar下的类。如果我们应用程序中想使用这个注解,需要添加一个JVM参数:-XX:-RestrictContended,填充的默认宽度为128字节,若需自定义宽度则可以用另一个参数:-XX:ContendedPaddingWidth=xxx

本文就到这里啦,若这篇文章对你有所帮助的话,点个赞再走叭!谢谢支持!

参考资料:

《Java并发编程之美》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/559802.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新闻资讯java开发_新闻资讯app开发的功能与意义

获取新闻的目的因人而异,但对获取新闻的需求是一样的。现在是移动互联网的时代。人们不再想依靠传统的手段,而把便利作为获取服务的核心。因此,开发新闻咨询app是必要的。其到来不仅意味着获得新闻登上新的阶梯,还因为画出了圆满的…

php实时上传多张图片,PHP实现多张图片上传预览功能

PHP实现多张图片上传预览功能,支持左右移动图片切换位置、删除图片,限制图片上传的数量等-向左移动图片function reverse_left(obj) {var obj_li obj.parents("li");var obj_prev obj_li.prev("li");if (obj_prev.hasClass("…

centos php 默认安装目录,centos系统中的软件安装目录在哪

centos系统中软件的默认安装目录一般在/usr/local或者/opt中。我们还可以通过whereis命令来查看软件的实际安装路径。命令:whereis功能介绍:在特定目录中查找符合条件的文件。这些文件的烈性应属于原始代码,二进制文件,或是帮助文…

php atlas,apache atlas是什么

Atlas是一组可伸缩和可扩展的核心基础治理服务——使企业能够有效和高效地满足Hadoop中的遵从性需求,并允许与整个企业数据生态系统进行集成。Apache Atlas为组织提供开放的元数据管理和治理能力,以建立其数据资产的目录,对这些资产进行分类和…

php2588,搞清楚一下必胜2588z和2582z哪个好点?都有些什么区别?内幕评测分析

这二个必胜2588z和2582z区别不是很大的哈,款式和配置是差不多的,只是必胜2582Z 2052Z更强一些,看个人需要吧,不过家用的话,这两款都是可以的,我自己用的是必胜2582Z 2052Z,款式多大气的&#xf…

超表面透镜相位matlab,基于超透镜的小F数大景深镜头的设计方法及应用与流程...

本发明涉及基于超透镜的小f数大景深镜头的设计方法及应用。背景技术:监控系统中采用的透镜往往要求具有尽量高的成像分辨率和尽量大的景深,通常情况下,高分辨率的透镜一般具有较小f数,大的景深又要求焦距较短。但是利用传统透镜的…

php等级证书,php银行开放平台接口1:php 对cer证书处理

做一个银行接口要进行证书解析和签名,然后验证获token银行开放平台提供了2个证书public.cer 证书 :里面只有公钥200090491595.pfx证书 :里面有公钥和私钥这里专门做public.cer的说明和处理,.cer为扩展的证书,就是一个x…

oracle 9i hwm,Oracle 10g HWM原理及性能优化

摘 要: HWM(High Water Mark)是表中已经使用过的存储空间与未使用过的存储空间之间的分界线,HWM对全表扫描的性能有非常大的影响。当全表扫描时,Oracle会读取HWM下所有的块,即使这些块中有很多是空块,空块的存在,也即是…

五款救急的linux文件恢复软件,五款救急的Linux文件恢复软件

BKJIA快译】文件有备份,啥子也不愁!文件无备份,啥子也白搭。但是,面对突如其来的悲剧,文件恢复软件来帮忙时可以尽量最小化减小损失。下面Linux用户需知的5款文件恢复软件:#1,Ddrescue主页&…

linux 网络路径中网络协议栈有几种,linux网络路径中网络协议栈有几种

网络路径有很多种,其中的linux网络路径是最常用的,也是最需要关注的。linux网络路径中网络协议栈有几种?电脑新装系统漏洞应不应该修复?了解网络安全常识,首先就要了解计算机网络安全有哪些基本注意事项,下面佰佰安全网小编就带…

华硕T100 安装linux,【华硕T100TA3740评测】双硬盘组合 华硕T100TA挑战存储极限(全文)_华硕 T100TA3740_笔记本评测-中关村在线...

一直以来产品线的细化和完善完全是在于对于行业空白的填补而实现的,比如笔记本电脑的推出就为了弥补人们移动办公的空白,而平板电脑的推出是为了弥补智能手机和笔记本电脑市场的空白。2010年推出的iPad可谓创造了一个全新的品类——平板电脑,…

用四位led数码管作显示器的篮球比赛24秒计时器求c语言代码,单片机编程控制LED七段数码管作显示的篮球赛计时计分系统...

本次设计用由AT89C51编程控制LED七段数码管作显示的球赛计时计分系统。系统应具有赛程定时设置,赛程时间暂停,及时刷新甲、乙双方的成绩以及赛后成绩暂存等功能。内容包括:显示、键盘、时钟等内容设计说明2.1需求分析2.1.1 计分系统分为“A队…

android 获取对话框对象,Android 基本Dialog和自定义Dialog

Android 基本Dialog和自定义DialogDialog类是对话框的基类,但你应该避免直接实例化Dialog ,可以使用子类1.AlertDialog 此对话框可以显示标题,最多三个按钮,可选择列表或自定义布局View.2.DatePickerDialog或TimePickerDialog 此对话框带有允…

android inset 标签,android – 有几个WindowInsets?

WindowInsets描述了一组窗口内容的插图.换句话说,WindowInsets有一个可用的应用程序区域(并有其他信息,如isRound).可用区域不包括StatusBar和NavigationBar的Rect.如果您只想知道StatusBar和NavigationBar的高度,请查看this.你可以得到如下的WindowInsets.以下示例使用WindowI…

android toolbar源码解析,深入理解Android 5.0中的Toolbar

环境说明:Android Studio 2.0V7包版本:com.android.support:appcompat-v7:23.4.0compileSdkVersion 23buildToolsVersion "24.0.0"Toolbar 引入使用XML布局中加入:android:id"id/toolbar"android:layout_width"matc…

android 9图片报错,Android2.1加载9Patch图片运行后报错

今天遇到一个很无语的问题,竟然是9Patch图片上多加了光晕效果。因为需要自定义Button,所以请用了9Patch图片,而且图片上面还有一点光晕效果,同样也被拉伸了,在2.2的系统上面正常能跑,2.1上面就出问题&#…

鸿蒙系统发布IT直播,华为开源平台上线:鸿蒙系统、方舟编译器在列

华为近日官方宣布,方舟编译器将于8月31日正式开源。这一颠覆式的技术堪称安卓系统性能革命,将带来巨大的性能提升,官方称操作流畅度提升可高达60%。8月31日凌晨,华为开源平台网站(HUAWEI OpenSource)就迫不及待地悄然上…

火车头采集html文档没内容,火车头采集器:编辑任务中常见问题

1.标题前面大量空白,应该如何采集?答:程序里有html过滤选项,你可以选中过滤这些空白字符,如果有些空白字符不在html过虑里,你可以在过滤选项里添加那些字符。2.同一个页面,很多相同内容,怎么分做为多条记录…

金字塔图表 html,Highcharts 柱形图(柱状图及条形图)之 金字塔图 演示

JS 代码:var categories [0-4, 5-9, 10-14, 15-19,20-24, 25-29, 30-34, 35-39, 40-44,45-49, 50-54, 55-59, 60-64, 65-69,70-74, 75-79, 80-84, 85-89, 90-94,95-99, 100 ];var chart Highcharts.chart(container, {chart: {type: bar},title: {text: 2015 年德…

angular html页面嵌套,使用AngularJS来实现HTML页面嵌套的方法

html不支持嵌入在html页面中的html页面。实现这一功能通过使用以下方式:使用ajax - 让一台服务器来调用获取相应的html页面,并将其设置在html控件的innerhtml。使用服务器端包含 - jsp,php等web端服务器技术可以在包括动态页面中的html页面。…