java高并发核心要点|系列4|CPU内存指令重排序(Memory Reordering)
今天,我们来学习另一个重要的概念。
CPU内存指令重排序(Memory Reordering)
什么叫重排序?
重排序的背景
我们知道现代CPU的主频越来越高,与cache的交互次数也越来越多。当CPU的计算速度远远超过访问cache时,会产生cache wait,过多的cache wait就会造成性能瓶颈。
针对这种情况,多数架构(包括X86)采用了一种将cache分片的解决方案,即将一块cache划分成互不关联地多个 slots (逻辑存储单元,又名 Memory Bank 或 Cache Bank),CPU可以自行选择在多个 idle bank 中进行存取。这种 SMP 的设计,显著提高了CPU的并行处理能力,也回避了cache访问瓶颈。
简单来说,现在CPU为了追求高性能,做了一些优化,这个优化就是重排序。
通过对指令重排,CPU可以获得更快地响应速度,但也给编写并发程序的程序员带来了诸多挑战。
重排序会引起多线程的可见性问题。
比如线程A和线程B看到的共享区数据会不一致。
那如何来解决这个问题呢?
答案是:内存屏障。
什么是内存屏障?
简单来说,就是一条指令,这条指令指示不要对这些代码或代码块进行重排序。
java世界中用关键字:volatile,来指定这个变量使用内存屏障,来保证穿上变量不会被重排序,从来达到解决数据的可见性问题。
事实上,java一般用volatile和CAS锁来实现线程间的数据同步,达到高性能,高并发。
那么,用了volatile和CAS锁,是否就高枕无忧了呢?
否!
这里还有一个坑,那就是:伪共享问题。
请听下节分解。
java高并发核心要点|系列4|CPU内存指令重排序(Memory Reordering)的更多相关文章
- java高并发核心要点|系列5|CPU内存伪共享
上节提到的:伪共享,今天我们来说说. 那什么是伪共享呢? 这得从CPU的缓存结构说起.以下如图,CPU一般来说是有三级缓存,1 级,2级,3级,越上面的,越靠近CPU的,速度越快,成本也越高.也就是说 ...
- java高并发核心要点|系列文章
java高并发核心要点|系列1|开篇 java高并发核心要点|系列2|锁的底层实现原理 java高并发核心要点|系列3|锁的底层实现原理|ABA问题 java高并发核心要点|系列4|CPU内存指令重排 ...
- java高并发核心要点|系列1|开篇
在java高并发编程,有几个很重要的内容: 1.CAS算法 2.CPU重排序 3.缓存行伪共享 我们先来说说高并发世界中的主要关键问题是什么? 是数据共享. 因为多线程之间要共享数据,就会遇到各种问题 ...
- java高并发核心要点|系列2|锁的底层实现原理
上篇文章,我们主要讲了解决多线程之间共享数据的核心问题和解决方案,也讲了锁的简单分类. 那么,这把锁,我们应该怎么去实现呢?如果你是java语言设计者,你又会怎么去设计这个线程锁呢? 直觉告诉我们,我 ...
- java高并发核心要点|系列3|锁的底层实现原理|ABA问题
继续讲CAS算法,上篇文章我们知道,CAS算法底层实现,是通过CPU的原子指令来实现. 那么这里又有一个情景: 话说,有一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且 ...
- 从菜鸟到大神:Java高并发核心编程(连载视频)
任何事情是有套路的,学习是如此, Java的学习,更是如此. 本文,为大家揭示 Java学习的套路 背景 Java高并发.分布式的中间件非常多,网上也有很多组件的源码视频.原理视频,汗牛塞屋了. 作为 ...
- java高并发核心类 AQS(Abstract Queued Synchronizer)抽象队列同步器
什么是AQS? 全称: Abstract Queued Synchronizer: 抽象队列同步器 是 java.util.concurrent.locks包下的一个抽象类 其编写者: Doug Le ...
- Java高并发和多线程系列 - 1. 线程基本概念
1. 什么是线程? 线程和进程的区别 在了解线程的概念前,我们应该先知道什么是进程? 进程是操作系统的基本概念之一, 它是正在执行的程序实例. * 下面的一些进程的基本概念你可以了解下 ------- ...
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
随机推荐
- maven将自己的springboot项目打包成jar包后,作为工具包引入其他项目,找不到jar中的类
将springboot项目打包成jar包,作为工具包导入项目后,找不到jar中的类. 原因是:springboot项目使用了自动的打包插件. 原先的插件配置: <build> <pl ...
- Azure Data Lake Storage Gen2实战体验
相较传统的重量级OLAP数据仓库,“数据湖”以其数据体量大.综合成本低.支持非结构化数据.查询灵活多变等特点,受到越来越多企业的青睐,逐渐成为了现代数据平台的核心和架构范式. 作为微软Azure上最新 ...
- Linux man及echo的使用
学习目标: 通过本实验掌握man和echo两个命令的用法. 实验步骤: 1.通过man查询ls的详细用法,后面可以跟哪些参数,每个参数的作用.这里主要查找如何禁止ls彩色结果输出. 2.把查找到的参数 ...
- 【Deep Learning Nanodegree Foundation笔记】第 1 课:INTRODUCTION Welcome
Welcome to the Deep Learning Nanodegree Foundations Program! In this lesson, you'll meet your instru ...
- SQL子连接案例
子查询 何时使用子查询 1. 子查询作为数据源 2. 数据加工 需求:根据不同顾客的所有的账户余额划分区间,进行分组 sql语句实现如下: select 'Small Fry' name , 0 lo ...
- hive udf编程教程
hive udf编程教程 https://blog.csdn.net/u010376788/article/details/50532166
- javaScript中==和===对数组、对象的判断是它们是否同一个实例对象
问题描述 在实现业务时,大量用到了 if(a === b)这样的判断,但有一个类似判断一直进不去这个if条件, a === b 返回的一直是false,但是其他几个类似判断,都正常触发条件. 原因 ...
- 洛谷 P1169 棋盘制作 题解
题面 这道题可以分成两部分来处理: 第一部分: 设f[i][j]表示右下角以(i,j)结尾的最大正方形的边长. 显然f[i][j]=min(f[i][j-1],f[i-1][j-1],f[i-1][j ...
- linux 终端的用户与主机名
首先这个属于Linux中的$PS1的变量,你可以通过 echo $PS1查看你当前的变量值. 默认的PS1变量值是 [\u@\h \W]\$,每个参数的含义 "root":表示当前 ...
- Luogu P2839 [国家集训队]middle
题目 首先我们考虑解决中位数一类问题的常用手段:二分\(mid\),将大于等于它的设为\(1\),小于它的设为\(−1\),判断区间和是否\(\ge0\). 对于询问\(a,b,c,d\),二分完\( ...