volatile关键字

150 阅读4分钟

1、什么是volatile关键字?

volatile关键字是Java中用来保证内存可见性、禁止指令重排的关键字。

2、volatile关键字有什么作用?

  1. 保证被修饰的变量对所有线程可见;
  2. 禁止指令重排序,从而保证线程执行顺序的可预见性;
  3. 在一定程度上可以用来保证线程安全。

3、volatile关键字可以保证线程安全吗?

volatile关键字不能保证线程安全,因为它只能保证可见性,不能保证原子性。例如,在一个volatile变量的自增操作中,多个线程同时读取并自增该变量的值,可能会导致数据错误。

4、volatile关键字和synchronized关键字有什么区别?

  • volatile关键字用于保证变量的可见性和禁止重排序,而synchronized关键字用于保证线程安全和同步;
  • volatile关键字只作用于变量,并不能作用于代码块或方法,而synchronized关键字可以作用于代码块和方法;
  • volatile关键字是一种轻量级的同步机制,不会引起线程上下文的切换和调度,而synchronized关键字会引起线程上下文的切换和调度。

5、volatile关键字和Atomic类有什么区别?

Atomic类是基于CAS(Compare and Swap)操作实现的原子操作类,可以保证线程安全和操作的原子性,而volatile关键字只能保证变量的可见性和禁止重排序;

Atomic类中提供了一些常用的原子操作方法,例如getAndIncrement(),compareAndSet()等,可以用来实现线程安全的自增和自减操作。

6、volatile关键字能保证原子性吗?

volatile关键字不能保证原子性,因此对于需要保证原子性的操作,仍然需要使用synchronized关键字或者Atomic类中的原子操作方法。

7、volatile关键字能保证变量的可见性吗?

volatile关键字可以保证变量的可见性,即一个线程修改了值后,其他线程能够立即看到修改的值。这是因为Java内存模型中规定,一个线程修改了共享变量的值后,必须立即把该值刷新到主内存中,其他线程再从主内存中读取最新的值。

8、volatile关键字的使用场景有哪些?

  • 作为开关标志,控制线程的执行;
  • 作为状态标志,对线程的状态进行控制;
  • 用于多线程间的数据通信,例如生产者消费者模型中的任务队列。

9、volatile关键字和final关键字有什么区别?

  • volatile关键字可以修饰变量,而final关键字可以修饰变量、方法和类;
  • volatile关键字用于保证变量的内存可见性和禁止重排序,一般用于多线程环境下,而final关键字用于定义不可变量,一般用于常量的定义和方法的重写限制;
  • volatile关键字不能保证原子性,而final关键字可以保证变量的赋值操作是原子性的。

10、volatile怎么实现可见性和保障有序性

Volatile如何保证有序性(禁止指令重排)

1、首先我们要了解计算机在执行程序时,为了提高性能,编译器和处理器一般都会对指令做重排,一般分为以下三种:

image.png

单线程环境里面确保程序最终执行的结果和代码顺序执行的结果一致。 处理器在进行指令重排时必须要考虑指令之间的数据依赖性。 多线程环境中线程交替执行,由于编译器优化重排的存在,两个或多个线程中使用的变量能否保证一致是不能确定的,最后执行的结果也是无法预测的。

2、volatile实现禁止指令重排优化,从而避免在多线程环境下程序出现乱排序执行的现象。 内存屏障,也称为内存栅栏,他是一个cpu的指令。作用有两个:

一是保证特定操作的执行顺序;

二是保证某些变量的内存可见性(volatile的内存可见性是利用该特性实现的)

3、由于编译器和处理器都能执行指令重排优化,如果在指令之间插入一条内存屏障则会告诉编译器和cup不管在任何情况下,无论任何指令都不能和这条内存屏障进行指令重排,也就是说通过插入内存屏障禁止在内存屏障前后的指令执行重排序优化。内存屏障的另外一个作用就是强制刷出各种CPU的缓存数据,因此在任何CPU上的线程都能读取到这些数据的最新值。

image.png