Volatile字段

1.Volatile特点

volatile就可以说是JVM提供的最轻量级的同步机制

  1. 不能保证原子性
  2. 保证可见性和禁止重排序

Java内存模型规定,将所有的变量都存放在主内存中,当线程使用变量时,会把主内存里面的变量复制到自己的工作空间中,线程读写变量时操作的是自己工作内存中的变量。
volatile确保对一个变量的更新对其他线程马上可见。线程在写入变量时不会把值缓存到寄存器或者其他地方,而是直接刷新到主内存。不能保证操作的原子性。

使用场景:
1.写入变量值不依赖变量的当前值
2.读写变量值没有加锁

2.volatile底层实现

2.1汇编层面

在这里插入图片描述
volatile变量在字节码级别没有任何区别,在汇编级别使用了lock指令前缀

lock是一个指令前缀,Intel的手册上对其的解释是:
Causes the processor’s LOCK# signal to be asserted during execution of the accompanying instruction (turns the instruction into an atomic instruction). In a multiprocessor environment, the LOCK# signal insures that the processor has exclusive use of any shared memory while the signal is asserted.

Lock后就是一个原子操作。原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。当使用 LOCK 指令前缀时,它会使 CPU 宣告一个 LOCK# 信号,这样就能确保在多处理器系统或多线程竞争的环境下互斥地使用这个内存地址。当指令执行完毕,这个锁定动作也就会消失。
lock前缀指令其实就相当于一个内存屏障。内存屏障是一组CPU处理指令,用来实现对内存操作的顺序限制。volatile的底层就是通过内存屏障来实现的。

链接:https://www.jianshu.com/p/2643c9ea1b82

3. Volatile 与 synchronized 区别

volatile的本质是告诉jvm,该变量在寄存器中的值是不确定的,需要在主存中读取,
synchronized关键字是锁住当前变量,只有当前线程可以访问,其他线程等待。

  1. volatile只能作用于变量,而synchronized可以作用于变量、方法和代码块

  2. 多线程访问volatile不会发生阻塞,而synchronized关键字可能发生阻塞。

  3. volatile能够保证数据的可见性,就是在多个线程之间是可见的,不能保证原子性,而synchronized关键字都可以保证。

  4. volatile关键字主要解决的是多个线程之间的可见性,而synchronized关键字保证的是多个线程访问资源的同步性。

Guess you like

Origin blog.csdn.net/chentaishan/article/details/118912361