1.1.1. Volatile关键字

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

  • 保证被volatile修饰的变量对所有线程都是可见的
  • 禁止进行指令重排序

1. volatile关键字禁止指令重排序:

当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见,在其后面的操作肯定还没有进行;

在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。

volatile可以保证可见性 有序性,但是无法保证原子性(++的情况)

Volatile原理

volatile如何实现内存可见性:通过加入内存屏障和禁止重排序来优化实现的。
  • 对volatile变量执行写操作时,会在写操作后加入一条store屏障指令;
  • 对volatile变量执行读操作时,会在读操作前加入一条load屏障指令。

2.Volatile的原理和实现机制

观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令

摘自《深入理解Java虚拟机》:

lock前缀指令实际上相当于一个 内存屏障(也成内存栅栏),内存屏障会提供3个功能:

  • 确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
  • 强制将对缓存的修改操作立即写入主存;
  • 如果是写操作,它会导致其他CPU中对应的缓存行无效。

3. synchronized 和 volatile 关键字的作用和区别

3.1作用
  • volatile 本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需从主存中读取;
  • synchronized则是锁定当前变量,只有当前线程可以访问该变量,其它线程被阻塞住。
3.2区别
  1. volatile 仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。

  2. volatile 仅能实现变量的修改可见性,并不能保证原子性;synchronized 则可以保证变量的修改可见性和原子性。

  3. volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。

  4. volatile 标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。

Copyright © tracyliu-FE 2021 all right reserved,powered by Gitbook文件修订时间: 2022-03-06 12:52:33

results matching ""

    No results matching ""