知识库
并发编程
  • 分类
  • 标签
  • 归档
友情连接

luoliang

吾生也有涯,知也无涯
并发编程
  • 分类
  • 标签
  • 归档
友情连接
  • volatile深度解析
    • synchronized原理
    • Java基础
    weiluoliang
    2024-04-10
    目录

    volatile深度解析

    # 简介

    根据java内存模型(JMM),区分共享内存区域和线程私有内存区域,线程对变量的修改不会马上同步到其他线程,所以在多线程间对公共变量修改,其他线程不会马上读到最新的数据。volatile关键字就是为了解决多线程间共享变量的可见性,只要在共享变量前加了volatile关键字,某线程修改公共变量后,其他线程立刻读到最新数据。

    # 可见性原理

    我们先看一段java代码示例

    public class Test1 {
    
        public static int a = 1;
        public int b = 2;
        public volatile int c = 3;
        public final int d = 4;
        private String s = "5";
        private Object o = new Object();
    
        public static void main(String[] args) {
            test();
        }
        public static void test() {
            System.out.println("1");
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    Javap命令查看字节码文件, javap -v Test1.class 。

    // 略。。
    // 自看最关键的地方,加了volatile关键字的会有 ACC_VOLATILE标识
     public volatile int c;
        descriptor: I
        flags: ACC_PUBLIC, ACC_VOLATILE
    
    1
    2
    3
    4
    5

    在JVM层面,如果发现ACC_VOLATILE标识,在写改字段的时候会添加lock前缀指令:lock cmpxchg %rdi,(%rdx), 该指令的作用:

    1. 该指令会将当前缓存数据回写到内存中。
    2. 其他处理器的缓存失效

    在早期的CPU,lock指令会锁总线,其他线程操作会阻塞,直到锁释放。现在比较新的CPU都是锁缓存,再结合缓存一致性(MESI)来保证数据同步。

    # 禁止指令重排序

    为了提高性能,JMM在保证不改变语义的情况下,可能会对指令进行重排序,添加了volatile关键字会阻止这种优化。

    # 附录

    # IDEA添加javap命令

    img

    命名: C:\dev\Java\jdk-1.8\bin\javap.exe
    参数:-v $OutputPath$\$FileDirRelativeToSourcepath$\$FileNameWithoutAllExtensions$.class
    工作目录: $ProjectFileDir$

    上次更新: 2024/04/10, 16:41:50
    synchronized原理

    synchronized原理→

    最近更新
    01
    Linux常用命令
    09-04
    02
    SpringBoot启动脚本
    08-31
    03
    安装监控grafana
    08-30
    更多文章>
    Theme by Vdoing | Copyright © 2022-2024 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式