聊聊 Volatile 的特点以及为何它能保证变量对所有线程的可见性

举报
赵KK日常技术记录 发表于 2023/06/30 23:20:43 2023/06/30
【摘要】 聊聊 Volatile 的特点以及为何它能保证变量对所有线程的可见性Volatile 是 Java 中一个非常特殊的关键字,它用于声明变量。这个关键字的特殊之处在于,它具有两个鲜明的特点:第一,保证变量对所有线程的可见性;第二,不保证原子性。今天,我们就来深入探讨一下 Volatile 这两个特点背后的原理,以及为何它能保证变量对所有线程的可见性。 Volatile 的特点 1. 保证变量...

聊聊 Volatile 的特点以及为何它能保证变量对所有线程的可见性

Volatile 是 Java 中一个非常特殊的关键字,它用于声明变量。这个关键字的特殊之处在于,它具有两个鲜明的特点:第一,保证变量对所有线程的可见性;第二,不保证原子性。今天,我们就来深入探讨一下 Volatile 这两个特点背后的原理,以及为何它能保证变量对所有线程的可见性。

Volatile 的特点

1. 保证变量对所有线程的可见性

当一个线程修改了 Volatile 变量的值后,这个变化对于其他线程是立即可见的。这意味着,无论哪个线程修改了 Volatile 变量,其他线程都能立即观察到这个变化。这种现象称为“可见性”。

2. 不保证原子性

尽管 Volatile 关键字能保证变量对所有线程的可见性,但它并不能保证操作的原子性。这意味着,在多个线程同时访问同一个 Volatile 变量时,有可能发生数据不一致的问题。例如,一个线程读取了 Volatile 变量的值,另一个线程在这个瞬间修改了该变量的值,那么第一个线程读取到的值可能不是最新的。

Volatile 保证可见性的原理

Volatile 关键字之所以能保证变量对所有线程的可见性,是因为它影响了 Java 内存模型(Java Memory Model,简称 JMM)中的两个重要规则:主内存和工作内存。
在 JMM 中,每个线程都有自己的工作内存,用于存储线程需要访问的变量副本。当一个线程需要读取一个变量时,它会首先在自己的工作内存中查找该变量的副本。如果找到了,那么就使用这个副本进行操作;如果找不到,就从主内存中读取该变量的最新值。
当一个线程修改了 Volatile 变量的值后,它会将修改后的值刷新到主内存中。这时,其他线程在访问该变量时,都会从主内存中读取最新的值,而不是使用自己工作内存中的副本。这样就保证了变量对所有线程的可见性。

Volatile 无法保证原子性的原理

尽管 Volatile 关键字能保证变量对所有线程的可见性,但它无法保证操作的原子性。这是因为 Java 内存模型允许多个线程同时访问同一个变量,而无需同步机制。当多个线程同时访问同一个 Volatile 变量时,有可能发生以下情况:

  • 线程 A 读取了 Volatile 变量的值。
  • 线程 B 修改了同一个 Volatile 变量的值。
  • 线程 A 使用读取到的值进行操作。
    在这个过程中,线程 A 读取到的值可能不是最新的,因为线程 B 在 A 读取值的瞬间修改了该变量。这导致了数据不一致的问题。要解决这个问题,需要使用其他同步机制,例如 synchronized 关键字或者原子操作类(如 AtomicInteger)。

结论

总之,Volatile 关键字在 Java 中具有特殊的地位,它保证了变量对所有线程的可见性,但无法保证操作的原子性。理解 Volatile 的特点和原理,有助于我们更好地利用它来解决多线程编程中的可见性问题,同时也提醒我们在面对原子性问题时,需要寻求其他同步机制的帮助。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。