volatile的作用

  • 保证变量在多线程中的可见性
  • 保证指令的有序性(禁止指令重排)

保证变量在多线程中的可见性

  1. 主存中有一个变量a, 它被volatile关键字所修饰, 并且它的值是0

  2. T1T2线程读取了变量a, 此时它们的线程的本地内存(CPU寄存器或高速缓存)中的值都是0

  3. 如果T1修改了变量a的值为1, 由于被a变量被volatile所修饰, 那么T1修改之后的a就会被刷新到主存(写屏障), 并且执行T2线程的CPU对a变量的缓存行会失效(读屏障), 强制从主存中获取值, 到达了多线程中变量的可见性的目的

  4. 通过内存屏障保证变量在多线程中的可见性, 如果字段被volatile修饰:

    • 读屏障: 在读指令前插入读屏障,可以让高速缓存中的数据失效重新从主内存加载数据
    • 写屏障: 在写指令之后插入写屏障,能让写入缓存的最新数据写回到主内存

保证指令的有序性(禁止指令重排)

指令重排的意义

  • JVM能够根据CPU的特性(CPU的多级缓存系统、多核处理器等)适当的重新排序机器指令,使机器指令更符合CPU的执行特点,最大限度的发挥CPU的性能,提高效率。

  • 单线程情况下, 指令重排没问题, 但是多线程环境下, 指令重排可能造成程序的执行结果并不是我们所期待的, 比如单例模式的DCL写法对DCL单例模式的思考

volatile通过两点保证指令有序性

happens-before

happens-before原则(定义一些禁止编译优化的场景,保证并发编程的正确性), 下图来源于: 来源《Java并发编程实践》

内存屏障

  • 编译器生成字节码时, 会在指令序列中插入内存屏障,会多出一个 lock 前缀指令

  • 内存屏障是一组处理器指令,解决禁止指令重排序和内存可见性的问题,保证指令重排序后与之前的输出结果一 样,使性能得到优化, 处理器在进行重排序时是会考虑指令之间的数据依赖性

  • 先于这个内存屏障的指令必须先执行,后于这个内存屏障 的指令必须后执行

使用 volatile 的经典场景

  • 双重校验锁 DCL(double checked locking)
  • ConcurrentHashMap哈希数组Node[]
  • 原子类例如AtomicIntegervalue属性
  • 多个线程操作同一块内存的同一个变量(保证有序性和内存可见性,有序性和可见性同等重要,都不能忽略)

volatile关键字简介的更多相关文章

  1. java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)

    概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...

  2. C语言中的volatile关键字简介

    C语言中的volatile关键字简介: (1)含义:         volatile关键字的意思是可能会被外来的意想不到的改变.它的作用是:优化器在使用该关键字定义的变量时,直接从内存中读取原始的数 ...

  3. volatile关键字与线程间通信

    >>Java内存模型 现在计算机普遍使用多处理器进行运算,并且为了解决计算机存储设备和处理器的运算速度之间巨大的差距,引入了高速缓存作为缓冲,缓存虽然能极大的提高性能,但是随之带来的缓存一 ...

  4. volatile关键字学习

    volatile关键字在实际工作中我用的比较少,可能因为我并不是造轮子的.但是用的少不是你不掌握的借口,还是要创造场景去使用这个关键字,本文将会提供丰富的demo. volatile 发音:英[ˈvɒ ...

  5. Java多线程学习(三)volatile关键字

    转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79680693 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...

  6. Java并发之(1):volatile关键字(TIJ21-21.3.3 21.3.4)

    Java并发Java服务器端编程的一项必备技能. ** 1 简介    volatile是java中的一个保留关键字,它在英语中的含义是易变的,不稳定的.volatile像final.static等其 ...

  7. 1.volatile关键字 内存可见性

    Java JUC 简介 在 Java 5.0 提供了 java.util.concurrent (简称JUC )包,在此包中增加了在并发编程中很常用的实用工具类,用于定义类似于线程的自定义子系统,包括 ...

  8. 【C# 线程】 volatile 关键字和Volatile类、Thread.VolatileRead|Thread.VolatileWrite 详细 完整

    overview 同步基元分为用户模式和内核模式 用户模式:Iterlocked.Exchange(互锁).SpinLocked(自旋锁).易变构造(volatile关键字.volatile类.Thr ...

  9. Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  10. volatile关键字 学习记录2

    public class VolatileTest2 implements Runnable{ volatile int resource = 0; public static void main(S ...

随机推荐

  1. HarmonyOS NEXT开发实战教程-记账app

    今天分享的实战教程是一款记账app,最近分享的项目都是纯页面,没有服务端,没有数据接口,因为鸿蒙开发主要就是写页面,都是前端嘛.如果有友友想要完整的项目可以找幽蓝君定制,想学服务端开发的话幽蓝君也可以 ...

  2. RPC实战与核心原理之网络通信

    架构设计:涉及一个灵活的RPC框架 回顾 RPC的通信原理及RPC中各个功能组件的作用 RPC就是把拦截到的方法参数,转成可以在网络中传输的二进制,并保证服务提供方能正确还原出语义,最终实现想调用本地 ...

  3. #React中类组件中关于回调函数的一个问题

    在ES6中,类中定义的方法,是放在原型对象的,供实例对象引用. //创建一个Person类 class Person { constructor(name,age) { this.name = nam ...

  4. post 报头注入

    1.user-agent 注入: 使用情况:万能密码无法绕过安全验证,用户名无法注入,通过查看源代码分析执行的动作. bp抓包修改user_agent的数据如下 User-Agent: ' or ud ...

  5. 【附源码】C语言的学生管理系统完整实现方案

    以下是一个基于C语言的学生管理系统完整实现方案,结合了结构体.链表.文件存储.菜单驱动等核心技术,参考了多个开源项目与课程设计案例. 系统支持管理员/学生双角色权限.数据持久化存储及完整增删改查功能, ...

  6. java的随机数Random

    测试1 1 package com.lv.study.pm.second; 2 3 public class TestMath { 4 5 public static void main(String ...

  7. tomcat为什么假死了.md

    现象 我们生产最近有个服务偶尔会挂掉,接口报错"connection reset by peer",上服务器curl也是同样报错,意思连接被server拒绝了. 通过dump以及日 ...

  8. SAP发布简易REST 二:API平台之接口配置

    API接口平台设计:(全JSON格式) 做ABAP的都知道,一般接口的处理都是封装个函数来单独处理.那么这些函数能不能做成配置呢?又以什么形式的参数来传入传出呢? ps:到目前为止,只是有点想法,所以 ...

  9. 用Java获取本机IP或者请求用户的真正IP地址

    一.在Web请求中获取请求用户的IP地址 public static String getUserRealIP(HttpServletRequest request) throws UnknownHo ...

  10. 直播预告丨《Flink提交流程&如何debug和跟踪流程(on yarn)》

    4月20日晚19点30分,袋鼠云数栈技术研发团队开发工程师--莫问,将会为大家直播分享<Flink提交流程&如何debug和跟踪流程(on yarn)>. 课程内容主要包括以下三点 ...