为什么在多线程写入值的情况下不能使用 volatile
why volatile can't be used in the case where one more threads will write value
很多文档提示我们不能用volatile
当多一个线程要写值的时候,比如有一个boolean对象isRun
,如果两个线程或者多个线程调用setIsRun(true/false)
,我们不能用volatile
修饰变量count
.
据我所知,volatile
可以使所有线程都可见最新值,那为什么我们不能在上述情况下使用它呢?任何人都可以告诉我这件事,谢谢!
如你所说。
volatile
- 保证线程之间的可见性。
synchronized
- 保证线程间的原子性和可见性。
示例:
假设有两个线程 A 和 B 都可以访问以下变量。
public volatile int count = 0;
如果线程 A 执行以下操作
count++;
不保证 JVM 执行 ++
操作,这是实际的 3 个 JVM 操作(读取、递增、写入)原子操作。如果存在竞争条件,线程 B 有可能看到过时的值被分配给 count
。
如果你想要原子性你需要使用synchronized
示例:
假设有两个线程 A 和 B 都可以访问以下变量和 increment
方法。
private volatile int count = 0;
public synchronized void increment() {
count++;
}
现在,如果线程 A 进入 increment
方法,它将获得一个实例级监视器锁,只有当它存在 increment
方法时才会释放该锁。这保证了JVM指令读、递增、写一个接一个执行。
很多文档提示我们不能用volatile
当多一个线程要写值的时候,比如有一个boolean对象isRun
,如果两个线程或者多个线程调用setIsRun(true/false)
,我们不能用volatile
修饰变量count
.
据我所知,volatile
可以使所有线程都可见最新值,那为什么我们不能在上述情况下使用它呢?任何人都可以告诉我这件事,谢谢!
如你所说。
volatile
- 保证线程之间的可见性。
synchronized
- 保证线程间的原子性和可见性。
示例:
假设有两个线程 A 和 B 都可以访问以下变量。
public volatile int count = 0;
如果线程 A 执行以下操作
count++;
不保证 JVM 执行 ++
操作,这是实际的 3 个 JVM 操作(读取、递增、写入)原子操作。如果存在竞争条件,线程 B 有可能看到过时的值被分配给 count
。
如果你想要原子性你需要使用synchronized
示例:
假设有两个线程 A 和 B 都可以访问以下变量和 increment
方法。
private volatile int count = 0;
public synchronized void increment() {
count++;
}
现在,如果线程 A 进入 increment
方法,它将获得一个实例级监视器锁,只有当它存在 increment
方法时才会释放该锁。这保证了JVM指令读、递增、写一个接一个执行。