【Java】Volitile的作用、JVM规范如何要求内存屏障、硬件层级内存屏障如何帮助java实现高并发 - 第二天笔记
第二天笔记
Volitile的使用
保持线程可见性
禁止指令重排:单线程中,两条指令的执行前后顺序不会影响执行结果,CPU流水线会优化执行顺序
如果存在乱序,则不可能出现x=0,y=0的结果
运行结果:出现了(0,0),说明语句发生了乱序(17、18行之间,或24、25行之间,发生了执行顺序交换)
乱序会产生严重后果吗?
DCL单例要不要加Volitile?
对象的创建过程:
1、执行new申请内存空间,m默认值是0
2、invokespecial 调用构造方法,m变为8
3、astore 将栈空间的t和堆空间的内存建立连接
DCL
饿汉式单例模式
懒汉式单例模式:DoubleCheck Lock 双重检测锁
是否可以先在判断null的时候直接加锁?从逻辑上没有问题,但是效率不高。
美团:上述单例的INSTANCE
是否需要加Volitile?需要!
恶汉是static的,class load的时候就被new了,是jvm级别的保证(只执行一次),不存在指令重排的问题,在服务起来的时候就初始化了,调用都是初始化之后的事情了
懒汉:加了volitile就能解决这个问题吗?是的。
JSR内存屏障
JSR规范规定:在任何JVM的实现中,被volitile修饰的变量不能发生重排。这是一个逻辑概念,是JVM层级的要求,不要直接理解为CPU级别的内存屏障。JVM实现为使用lockctl指令。
Load:读
Store:写
JVM层级的实现:(这个问题只有阿里问过)
如果要写,则上面加StoreStore
屏障,下面加StoreLoad
屏障
如果要读,则上面加LoadLoad
屏障,下面加LoadStore
屏障
Happens-Before原则:规定了哪些指令在执行的时候不可以重排序,需要加屏障(以下8种情况)
as if serial:(可能一些书中会提到这个术语)不管如何重排序,单线程执行结果不会改变,不会影响数据最终一致性。
以上都是概念,下面我们来看具体实现
Volatile如何保证一致性?
一般情况下,多核共享一个L3,而每个核心拥有自己的L1,L2
从内存往L3读数据的时候,按块读取,一次读取一个缓存行cache line
,一个缓存行一般为64字节
按块读取,是因为根据程序局部性原理,可以提高效率
充分发挥总线 CPU针脚等一次性读取更多数据的能力
缓存行64字节是怎么确定的?和总线宽度没有关系,这是一个工业上的折中值。
以缓存行为单位保持一致性:如果一行数据失效了,会通知其他缓存去更新。
这和volitile无关,每个机器都已经实现。见:MESI缓存一致性协议(针对Intel CPU的协议)
其他协议:MSI MESI MOSI Synapse Firefly Dragon
整个程序执行完从3秒优化成1秒多:在变量x前后,添加56字节的冗余变量,这样保证不再同一个缓存行64字节,不需要来回通知更新。两个CPU里面访问的x不需要通知其他CPU
单机最快的消息队列:鼻祖是RingBuffer。里面进行了很多先顾不到的优化,其中之一就使用了填充缓存行的方式。后来,好多队列都采用了RingBuffer解决方案。
解决缓存行的伪共享问题,提高效率
拓展
WC - 合并写技术
WCBuffer只有4个字节,CPU写的时候要凑满4字节才写一次。
下面这个例子可以证明WCBuffer的存在,它的运行结果为,两次循环比一次循环执行的速度更快,因为凑出了4个字节,写入效率高。
【Java】Volitile的作用、JVM规范如何要求内存屏障、硬件层级内存屏障如何帮助java实现高并发 - 第二天笔记相关推荐
- 《Java并发编程入门与高并发面试》or 《Java并发编程与高并发解决方案》笔记
<Java并发编程入门与高并发面试>or <Java并发编程与高并发解决方案>笔记 参考文章: (1)<Java并发编程入门与高并发面试>or <Java并发 ...
- Java高并发程序设计学习笔记(十一):Jetty分析
转自:https://blog.csdn.net/dataiyangu/article/details/87894253 new Server() 初始化线程池 QueuedThreadPool ex ...
- SpringBoot、Redis轻松实现Java高并发秒杀系统笔记
秒杀项目 优极限[完整项目实战]半天带你用SpringBoot.Redis轻松实现Java高并发秒杀系统 文章目录 秒杀项目 技术栈 课程介绍 学习目标 如何设计一个秒杀系统 项目搭建 分布式会话 登 ...
- Java秒杀系统方案优化 高性能高并发实战 学习笔记
秒杀系统 (一)搭建环境 自定义封装Result类 自定义封装CodeMsg类 集成redis和rabbit 封装RedisService类 断言和日志测试 (二)实现用户登录和分布式Session ...
- 《实战 Java 高并发程序设计》笔记——第3章 JDK 并发包(二)
文章目录 3.2 线程复用:线程池 3.2.1 什么是线程池 3.2.2 不要重复发明轮子:JDK 对线程池的支持 1. 固定大小的线程池 2. 计划任务 3.2.3 刨根究底:核心线程池的内部实现 ...
- java架构知识点-大数据与高并发(学习笔记)
大数据与高并发 一.秒杀架构设计 业务介绍 什么是秒杀?通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动 比如说京东秒杀,就是一种定时定量秒杀,在规定的时间内,无论商品是否秒杀完毕,该场次的秒 ...
- JAVA高并发服务器工作笔记0001---Java中InetAddress与InetSocketAddress的基本用法
技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 一.InetAddress:类的主要作用是封装IP及DNS,因为这个类没有构造器,所以我们要用他的 ...
- java实现递归下降分析_使用递归实现检查未知层级目录中的文件-Java实用技能
现在有这样一个需求,给你一个目录,需要你在此目录中查找全部名字中包含指定字符的文件. 这题的主要难点在于:目录中可能包含子目录,子目录中又会包含子目录.而我们事先没办法确定子目录到底有多少层!这时候就 ...
- Java高并发程序设计学习笔记(五):JDK并发包(各种同步控制工具的使用、并发容器及典型源码分析(Hashmap等))...
转自:https://blog.csdn.net/dataiyangu/article/details/86491786#2__696 1. 各种同步控制工具的使用 1.1. ReentrantLoc ...
最新文章
- End Credits
- 2006鄂土整项目精神
- 特性(C# 和 Visual Basic)
- 阿里PB级Kubernetes日志平台建设实践
- 灵魂拷问,上 Kubernetes 有什么业务价值?
- 安装JDK时提示 IllegalArgumentException:Invalid characters in hostname的解决方法
- hashcode、equals
- mysql5.7 json特性_mysql5.7新增加的JSON数据类型特征介绍
- String 尺取法
- 测试的重要性:蚊子让快递柜的触摸失灵
- 牛客网算法题目-最优乘车题解
- MyApps接口引擎,打破跨系统间的壁垒
- Java代码实现24点计算
- Bulma CSS - 简介
- 进程间通信的方式有哪些?
- 葵花宝典:软件开发高手是这样炼成的![转]
- Exception:There is no getter for property named ‘qo‘ in ‘class cn.xxxxxx.rbac.qo.XxxxQo 的两种错误可能及解决方案
- 高分一号、二号样例数据下载
- [转载]尺度函数与小波函数
- tplink打印机服务器重置,TP-Link无线路由器打印机设置指南