volatile变量的特性
1.保证可见性,不保证原子性
- 当写一个volatile变量时,JMM会把该线程本地内存中的变量强制刷新到主内存中(内存屏障)。
- 这个写操作会导致其他线程中的volatile变量缓存无效(消息总线)。
禁止指令重排
重排序是指编译器和处理器为了优化程序性能而对指令序列进行排序的一种手段。重排序需要遵守一定规则:
(1)重排序操作不会对存在数据依赖关系的操作进行重排序。 (2)重排序是为了优化性能,但是不管怎么重排序,单线程下程序的执行结果不能被改变。
volatile不适用的场景
volatile 不适合复合操作,比如 a++不是一个原子性操作,是由读取、加、赋值三步组成,所以在多线程操作下,不会达到预期目标。
voltile原理
volatile 关键字主要用于确保多线程之间对共享变量的可见性。当一个线程对 volatile 变量进行写操作时,它会将变量的最新值刷新到主内存中,而其他线程读取该变量时会从主内存中获取最新的值。
volatile 关键字通过内存屏障(Memory Barrier)来确保可见性。内存屏障是一种硬件或者软件屏障,它指示编译器和CPU在屏障两侧的指令不会被重排序,保证了在执行屏障之前的操作完成后,屏障两侧的操作才能执行。
当一个线程写入一个 volatile 变量时,它会发出写屏障,这确保了在写入该变量之前的所有操作已经完成。当另一个线程读取这个 volatile 变量时,它会发出读屏障,这确保了读取该变量后的所有操作都能看到最新的值。这样,volatile 关键字确保了对变量的写入和读取操作都不会与其他指令发生重排序,从而确保了可见性。
综上所述,volatile 关键字通过内存屏障的机制,防止了编译器和CPU对指令的重排序,确保了对 volatile 变量的写入和读取操作具有一定的原子性,从而确保了可见性。其他线程能够看到最新的 volatile 变量值,而不是使用本地线程缓存中的旧值。