volatile 关键字

  1. 0x00 Java 中 volatile 的原理
  2. 0x01 volatile 的作用
  3. 0x02 volatile 在什么情况下能保证安全

先说结论. volatile 降低了并发风险而非解决了风险. volatile 并不是万能的且用且珍惜.
volatile 只能保证读当前值的准确. 但毕竟任意操作一定是另一条指令.
使用了volatile只是会降低分析复杂代码的成本.尽量保护 volatile 变量的准确性.

0x00 Java 中 volatile 的原理

可见性:

  • 当一个线程修改了一个 volatile 变量的值,其他线程能够立即看到这个变化。
  • 这是因为 JVM 规范要求 volatile 变量的写操作会将新值直接写入主内存,并且通知其他线程该变量已被修改。
  • 同样,volatile 变量的读操作会从主内存中读取该变量的最新值。

禁止指令重排序:

  • 在编译器和处理器优化代码时,可能会对代码进行重排序以提高执行效率。
  • 但是这种重排序可能会导致多线程程序中的错误行为。
  • 使用 volatile 可以禁止某些类型的指令重排序,保证代码按照程序员预期的顺序执行。

不保证原子性:

  • 尽管 volatile 提供了可见性和有序性,但它并不保证复合操作的原子性。
  • 例如,即使使用 volatile 定义了一个整型变量,对该变量进行加减操作仍然可能不是原子性的。

0x01 volatile 的作用

假设有一个 volatile 整型变量 counter:

1
private volatile int counter = 0;

即使 counter 被声明为 volatile,以下的自增操作 (counter++) 仍然不是原子的:

1
counter++;

这个操作实际上包含了以下步骤:

  1. 读取 counter 的当前值。
  2. 将读取的值加一。
  3. 写回新的值到 counter。

如果多个线程同时执行 counter++, 因为不同的线程可能读取相同的旧值,然后各自独立地增加并写回相同的值,导致 counter 的值比预期的小。

0x02 volatile 在什么情况下能保证安全

  1. 变量的读写操作是原子的
    对于基本类型如 int, long (当启用 64 位架构的原子性支持时), float, double (同样当启用 64 位架构的原子性支持时) 等,单一的读写操作是原子的。这意味着这些操作不会被其他线程中断。

  2. 变量的更新不依赖于旧值
    如果对 volatile 变量的操作不依赖于其当前值,那么这样的操作可以认为是安全的。例如,简单的赋值操作 x = y; 不依赖于 x 的当前值。

  3. 变量不与其他状态一起参与不变约束
    如果一个 volatile 变量的更新不依赖于其他变量的状态,那么它可以被视为安全的。例如,如果有两个变量 x 和 y,而 x 是 volatile 的,那么仅对 x 的更新是安全的,只要这个更新不依赖于 y 的值。

  4. 仅有一个线程修改变量
    即使多个线程读取 volatile 变量,只要有一个线程负责修改该变量,那么这个变量的更新也是安全的。这是因为 volatile 变量的更新对所有线程都是可见的,所以其他线程总是能看到最新的值。

注意事项

尽管 volatile 可以在上述情况下保证一定程度的安全性,但要注意以下几点:

  • 复合操作:涉及多个步骤的操作(如 value++ 或 value += 1)并不是原子的,因此在多线程环境下可能会出现问题。
  • 复合状态:如果多个 volatile 变量一起参与某个不变约束,那么需要更复杂的同步机制来确保线程安全。
  • 初始化问题:volatile 不能保证对象的初始化顺序,因此在构造函数中初始化 volatile 字段时需要特别小心。

综上所述,volatile 关键词可以在满足特定条件的情况下保证一定程度的安全性,特别是在单一线程更新 volatile 变量,且操作不依赖于变量当前值的情况下。然而,对于更复杂的多线程同步需求,通常还需要结合其他的同步机制。

文章标题:volatile 关键字

本文作者:zhu8fei

发布时间:2024-08-14, 10:40:10

最后更新:2024-08-15, 09:37:02

原始链接:http://www.zhu8fei.com/2024/08/14/volatile.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 zhu8fei@163.com

目录
×

喜欢就点赞,疼爱就打赏