java并发 cpu高_java高并发核心要点|系列5|CPU内存伪共享
上节提到的:伪共享,今天我们来说说。
那什么是伪共享呢?
这得从CPU的缓存结构说起。以下如图,CPU一般来说是有三级缓存,1 级,2级,3级,越上面的,越靠近CPU的,速度越快,成本也越高。也就是说速度方面:1级>2级>3级。
图1
图2
如上图2我们来看看不同级别的缓存的时延:
到CPU的延迟CPU时钟耗时
主内存
很多(Multiple)
~60-80 ns
L3 缓存
~40-45 周期
~15 ns
L2 缓存
~10 周期
~3 ns
L1 缓存
~3-4 周期
~1 ns
寄存器
一周期
小于1ns,飞快
更多CPU架构信息:https://blog.csdn.net/karamos/article/details/80126704
说到这里,我们要理解一个很重要的概念:缓存行。什么是缓存行?
首先我们来看这几级缓存,其中,1,2级缓存是CPU核心私有的,也就是说每个核,之间不会共享1,2级缓存,那它们之间怎么通信或共享数据呢?
答案是:3级缓存,如下图:
那core1,和core2之间,是通过什么方式共享缓存呢?
答案是:缓存行!
什么是缓存行?简单来说,就是CPU内核之间共享数据的最小单位。如下图:x,y是在同一个缓存行,那每次CPU内核之间通信时交换x,y值,可以同时共享两个值。是不是很高效?
是的,一般情况下,如果x,y是属于数组内的数据 ,是可以达到高效共享数据的功能,但问题又来了:如果,x,y并不属于同一数组,x属于core1,而y属于core2,这个时候,如果core1更新了x,会导致y值失效了。为什么失效了,因为他们在同一缓存行。这时,只有把缓存行 flush到主存后, 其他内核中的相应的缓存行才会被置为过期数据,而缓存行什么时候flush到memory, 这个是有一定延时的 ,在这个延时当中, 其他CPU core是无法得知你的更新的 。那么内核core2再去读取Y的值时,由于L1的缓存里的数据已失效,那么就需要从L3获取,然后放入L2,再放入L1。 这样核心2读取Y值就需要从L3级的缓存读了。但是明明是内核core1修改的X的值,却影响到内核2去读取Y值了。同理,如果是内核2去修改Y的值,也会影响内核1去读取X的值。
简单来说,x,y同放在缓存行,而且它们又属于不同CPU内核的数据值(事实上CPU内核也就是代码中的:线程)。那就会因为各自更新其中一个值,而导致缓存失效。
这就是著名的伪共享问题。
有没有什么解决方案呢?
有的。
方案是:缓存行填充。
还是回到上面的例子,如果x,y同放到同一个缓存行,会造成伪共享。很简单,那就不要放在一起好了!
比如:x有8byte(字节),而一般缓存行总共有64byte。那其他剩下的位置,我们就用预定的空变量填充就行了,代码如下 (java6版本):
public final static classVolatileLong {
public volatile long x= 0L;
public long p1, p2, p3, p4, p5, p6,p7;//缓存行填充}
这个时候,core1更新x值,也就不会影响y值,从而造成伪共享问题。
上面的代码是java6的解决方案。
JAVA 8下的方案
在JAVA 8中,缓存行填充终于被JAVA原生支持了。JAVA 8中添加了一个@Contended的注解,添加这个的注解,将会在自动进行缓存行填充,如下代码:
import sun.misc.Contended;
@Contended
public class VolatileLong {
public volatile long value = 0L;
}
执行时,必须加上虚拟机参数-XX:-RestrictContended,@Contended注释才会生效。很多文章把这个漏掉了,那样的话实际上就没有起作用。
这就是伪共享的解决方案,多么简单!
本系列完毕!
如果各位读者,还有什么意见或建议,欢迎拍砖吐槽!
java并发 cpu高_java高并发核心要点|系列5|CPU内存伪共享相关推荐
- java并发多线程面试_Java多线程并发面试问答
java并发多线程面试 Today we will go through Java Multithreading Interview Questions and Answers. We will al ...
- java高并发递增编号_java 高并发 订单编号递增(解决方案)
业务描述: 首先从数据中查找最近的一条订单数据,然后将之前的订单号码+1作为新的订单号码,插入到数据库当中.(需求不能改变) 当出现并发操作时,A从数据库中获取最近一条订单的订单号为N,这是A还没有完 ...
- java 单线程 并发_单线程_Java高并发专题系列_Java视频-51CTO学院
Apache Kafka® 是 一个分布式流处理平台. Apache Kafka 是 一个分布式流处理平台. 1. 可以让你发布和订阅流式的记录. 2. 这一方面与消息队列或者企业消息系统类似. 3. ...
- java service层 事务_Java高并发秒时啊API之Service层1
---2-1 使用Spring托管Service依赖理论---------------------------- spring ioc优势(工厂模式): 1.对象创建统一托管 2.规范的生命周期管理 ...
- java queue源码_Java高并发系列之ArrayBlockingQueue源码解析
JUC包下定义了一个接口:BlockingQueue.其实现类有ArrayBlockingQueue等.本文先来介绍一下ArrayBlockingQueue.从字面可以看出,ArrayBlocking ...
- java如何保证数据安全_java高并发下怎么保障数据安全?有哪些办法?
近些年科技发展水平越来越快速了,这也促使了大家对于新兴软件的学习.尤其是对于java的渴求更是明显,这也进一步说明了java功能的强大.今天就来为大家介绍一下java高并发下怎么保障数据安全以及有哪些 ...
- java的并发和并行_JAVA中并发和并行
关于并发和并行 对于JAVA的并发和并行,是重要的知识点. 开始很多人都会有疑惑,并发和并行差不多啊,意思很相近啊,其实它们是有很大区别的. 并发:早期的CPU只有单核,你可以在电脑上看电视,聊天,刷 ...
- java中thread实例_Java多线程并发执行demo代码实例
主类:MultiThread,执行并发类 package java8test; import java.util.ArrayList; import java.util.List; import ja ...
- java 多线程 变慢_java多线程并发程序执行慢有什么原因?该怎么解决?
我们在执行java多线程并发程序时有时候会碰到执行特别慢的场景,小伙伴们知道是什么原因导致的吗?它要怎么解决呢?下面小编就为你讲讲. 前提:在某地需要开发一个应用系统,此系统主要功能是能够让一些中小型 ...
最新文章
- 学完UI设计可以从事哪些工作
- 2016 ICPC World Finals -Ceiling Function
- mysql命令导入导出数据_mysql命令行导入和导出数据
- Linux查看用户信息/查看所有用户信息的命令
- 在.NET中使用Speex -- 音频数据编解码
- 调色师必须了解的LUT知识
- 下拉框根据输入文字自动选择和输入提示
- 1029. 旧键盘(20)-PAT乙级真题
- SQL 递归树 子父节点相互查询
- leetcode 175. Combine Two Tables
- 源码搜索引擎,让你找到更适合你的源码
- w10打开网络计算机退出,Win10网络发现已关闭怎么办?|Win10启用网络发现方法
- 单细胞测序的入门操作
- 企业宣传片解说词的写法指导。
- web前端开发期末大作业 ——个人主页(可自取源码)
- 战术板将要下岗 iPad登陆橄榄球场
- 单片机 并口 控制爱普生打印机开发流程记录
- 第三周作业#183;
- CentOS 7 安装Ibus中文输入法
- 【408】计算机统考科目知识整理
热门文章
- python—while循环、字符串
- 第 5-2 课:线程池——ThreadPoolExecutor + 面试题
- 解决exe文件在别人电脑上运行缺失文件情况
- C语言空指针NULL详解
- android怎么升级版本5.0,一加手机怎么升级安卓5.0系统
- ping 工具开发日记(1)
- python3字符串转数字_Python3基础语法和基本数据类型
- 台式计算机更新不了,台式机更新造成电脑关不了机怎么办
- 将你一张表的值覆盖_精准度可达亚米级,山东“北斗一张网”向社会免费开放...
- oracle varchar默认长度_面试官:如何精确计算mysql数据库索引长度?