Java 中的 volatile int 是线程安全的吗?
Java 中的 volatile int
是线程安全的吗?也就是说,可以在不加锁的情况下安全地读取和写入吗?
Is a volatile int
in Java thread-safe? That is, can it be safely read from and written to without locking?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
是的,您可以安全地读取它并写入它 - 但您不能执行任何复合操作,例如安全地递增它,因为这是一个读/修改/写周期。还有一个问题是它如何与其他变量的访问交互。
坦率地说,易失性的确切性质令人困惑(请参阅 JLS 的内存模型部分了解更多详细信息) - 我个人通常会使用
AtomicInteger
相反,作为确保我做对的更简单的方法。Yes, you can read from it and write to it safely - but you can't do anything compound such as incrementing it safely, as that's a read/modify/write cycle. There's also the matter of how it interacts with access to other variables.
The precise nature of volatile is frankly confusing (see the memory model section of the JLS for more details) - I would personally generally use
AtomicInteger
instead, as a simpler way of making sure I get it right.是的,读取将始终导致最后写入的值,(并且读取和写入都是原子操作)。
易失性读/写在执行中引入了所谓的发生之前关系。
来自 Java 语言规范 第 17 章:线程和锁
换句话说,在处理易失性变量时,您不必显式同步(引入发生-before关系)使用
synchronized
关键字以确保线程获得写入变量的最新值。但正如 Jon Skeet 指出的那样,易失性变量的使用是有限的,通常您应该考虑使用 java.util.concurrent 包中的类。
Yes, a read will always result in the value of the last write, (and both reads and writes are atomic operations).
A volatile read / write introduces a so called happens-before relation in the execution.
From the Java Language Specification Chapter 17: Threads and Locks
In other words, when dealing with volatile variables you don't have to explicitly synchronize (introduce a happens-before relation) using
synchronized
keyword in order to ensure that the thread gets the latest value written to the variable.As Jon Skeet points out though, the use of volatile variables are limited, and you should in general consider using classes from the
java.util.concurrent
package instead.Java 中对 volatile int 的访问将是线程安全的。当我说访问时,我指的是对其进行单元操作,例如 volatile_var = 10 或 int temp = volatile_var (基本上是使用常量值进行写入/读取)。 java中的Volatile关键字确保了两件事:
然而,Jon Skeet 正确地提到,在非原子操作 (volatile_var = volatile + 1) 中,不同的线程可能会得到意外的结果。
Access to volatile int in Java will be thread-safe. When I say access I mean the unit operation over it, like volatile_var = 10 or int temp = volatile_var (basically write/read with constant values). Volatile keyword in java ensures two things :
However Jon Skeet mentions rightly that in non atomic operations (volatile_var = volatile + 1) different threads may get unexpected result.
1)如果两个线程都在读取和写入共享变量,那么使用 volatile 关键字是不够的。在这种情况下,您需要使用同步来保证变量的读写是原子的。读取或写入易失性变量不会阻止线程读取或写入。为此,您必须在关键部分周围使用同步关键字。
2) 作为同步块的替代方案,您还可以使用 java.util.concurrent 包中的多种原子数据类型之一。例如,AtomicLong 或 AtomicReference 或其他之一。
如果您有一个写入器线程和多个读取器线程,那么它是线程安全的。
注意:如果 helper 是不可变的,则不需要 volatile 关键字。这里单例将正常工作。
如果计数器由多个线程递增(读写操作),则不会给出正确的答案。这种情况也可以通过竞争条件来说明。
注意:这里 volatility 没有帮助。
1) If two threads are both reading and writing to a shared variable, then using the volatile keyword for that is not enough. You need to use a synchronized in that case to guarantee that the reading and writing of the variable is atomic. Reading or writing a volatile variable does not block threads reading or writing. For this to happen you must use the synchronized keyword around critical sections.
2) As an alternative to a synchronized block you could also use one of the many atomic data types found in the java.util.concurrent package. For instance, the AtomicLong or AtomicReference or one of the others.
It's thread safe if you have one writer thread and multiple reader threads.
Note : If helper is immutable then no need of volatile keyword.Here singleton will work properly.
In case of counter which is being incremented by multiple threads (reading writing operation) will not give correct answer. This condition is also illustrated by race condition.
NOTE : Here volatile will not help.
如果易失性变量不依赖于任何其他易失性变量,则其读操作的线程安全。如果写了 volatile 并不能保证线程安全。
假设你有一个易失性变量 i,它的值取决于另一个易失性变量 j。现在Thread-1访问变量j并递增它,并且即将从CPU缓存更新到主内存中。如果 Thread-2 读取
Thread-1之前的变量i实际上可以更新主存中的j。 i 的值将根据 j 的旧值,这是不正确的。也称为脏读。
If a volatile is not dependent on any other volatile variable its thread safe for read operation. In case of write volatile does not guarantee thread safety.
Assume you have a variable i which is volatile and its value is dependent on another volatile variable say j. Now Thread-1 access variable j and increment it and is about to update it in main memory from CPU cache. In case the Thread-2 reads the
variable i before Thread-1 can actually update the j in main memory. The value of i will be as per the old value of j which would be incorrect. Its also called Dirty read.
并非总是如此。
如果多个线程正在写入和读取变量,则它不是线程安全的。如果您有一个写入器线程和多个读取器线程,那么它是线程安全的。
如果您正在安全地寻找 Thread,请使用 AtomicXXX 类
请参阅下面帖子中的 @teto 答案:
Volatile 布尔值与 AtomicBoolean
Not always.
It's not thread safe if multiple threads are writing and reading the variable. It's thread safe if you have one writer thread and multiple reader threads.
If you are looking for Thread safely, use AtomicXXX classes
Refer to @teto answer in below post:
Volatile boolean vs AtomicBoolean