第二天笔记

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实现高并发 - 第二天笔记相关推荐

  1. 《Java并发编程入门与高并发面试》or 《Java并发编程与高并发解决方案》笔记

    <Java并发编程入门与高并发面试>or <Java并发编程与高并发解决方案>笔记 参考文章: (1)<Java并发编程入门与高并发面试>or <Java并发 ...

  2. Java高并发程序设计学习笔记(十一):Jetty分析

    转自:https://blog.csdn.net/dataiyangu/article/details/87894253 new Server() 初始化线程池 QueuedThreadPool ex ...

  3. SpringBoot、Redis轻松实现Java高并发秒杀系统笔记

    秒杀项目 优极限[完整项目实战]半天带你用SpringBoot.Redis轻松实现Java高并发秒杀系统 文章目录 秒杀项目 技术栈 课程介绍 学习目标 如何设计一个秒杀系统 项目搭建 分布式会话 登 ...

  4. Java秒杀系统方案优化 高性能高并发实战 学习笔记

    秒杀系统 (一)搭建环境 自定义封装Result类 自定义封装CodeMsg类 集成redis和rabbit 封装RedisService类 断言和日志测试 (二)实现用户登录和分布式Session ...

  5. 《实战 Java 高并发程序设计》笔记——第3章 JDK 并发包(二)

    文章目录 3.2 线程复用:线程池 3.2.1 什么是线程池 3.2.2 不要重复发明轮子:JDK 对线程池的支持 1. 固定大小的线程池 2. 计划任务 3.2.3 刨根究底:核心线程池的内部实现 ...

  6. java架构知识点-大数据与高并发(学习笔记)

    大数据与高并发 一.秒杀架构设计 业务介绍 什么是秒杀?通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动 比如说京东秒杀,就是一种定时定量秒杀,在规定的时间内,无论商品是否秒杀完毕,该场次的秒 ...

  7. JAVA高并发服务器工作笔记0001---Java中InetAddress与InetSocketAddress的基本用法

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 一.InetAddress:类的主要作用是封装IP及DNS,因为这个类没有构造器,所以我们要用他的 ...

  8. java实现递归下降分析_使用递归实现检查未知层级目录中的文件-Java实用技能

    现在有这样一个需求,给你一个目录,需要你在此目录中查找全部名字中包含指定字符的文件. 这题的主要难点在于:目录中可能包含子目录,子目录中又会包含子目录.而我们事先没办法确定子目录到底有多少层!这时候就 ...

  9. Java高并发程序设计学习笔记(五):JDK并发包(各种同步控制工具的使用、并发容器及典型源码分析(Hashmap等))...

    转自:https://blog.csdn.net/dataiyangu/article/details/86491786#2__696 1. 各种同步控制工具的使用 1.1. ReentrantLoc ...

最新文章

  1. End Credits
  2. 2006鄂土整项目精神
  3. 特性(C# 和 Visual Basic)
  4. 阿里PB级Kubernetes日志平台建设实践
  5. 灵魂拷问,上 Kubernetes 有什么业务价值?
  6. 安装JDK时提示 IllegalArgumentException:Invalid characters in hostname的解决方法
  7. hashcode、equals
  8. mysql5.7 json特性_mysql5.7新增加的JSON数据类型特征介绍
  9. String 尺取法
  10. 测试的重要性:蚊子让快递柜的触摸失灵
  11. 牛客网算法题目-最优乘车题解
  12. MyApps接口引擎,打破跨系统间的壁垒
  13. Java代码实现24点计算
  14. Bulma CSS - 简介
  15. 进程间通信的方式有哪些?
  16. 葵花宝典:软件开发高手是这样炼成的![转]
  17. Exception:There is no getter for property named ‘qo‘ in ‘class cn.xxxxxx.rbac.qo.XxxxQo 的两种错误可能及解决方案
  18. 高分一号、二号样例数据下载
  19. [转载]尺度函数与小波函数
  20. tplink打印机服务器重置,TP-Link无线路由器打印机设置指南

热门文章

  1. 洛谷 - P3254 圆桌问题(最大流+路径打印)
  2. (转)区间合并pushup函数模板
  3. 正整数 java_JAVA语言:正整数A+B(Java)PAT团体程序设计题解
  4. EXE与SYS通信(其他模式)
  5. (十二)boost库之多线程高级特性
  6. 详解Windows内存分页机制
  7. 深度探索I/O完成端口
  8. Java NIO 介绍和基本demo
  9. 后悔!我早该把这1W字详解的 InnoDB 原理给你!
  10. Redis持久化的几种方式——RDB深入解析