我想弄清楚下面的代码是否存在任何潜在的并发问题。具体来说,与 volatile 变量相关的可见性问题。 Volatile 定义为:此变量的值永远不会在线程本地缓存:所有读取和写入都将直接进入“主内存”
public static void main(String [] args)
{
Test test = new Test();
// This will always single threaded
ExecutorService ex = Executors.newSingleThreadExecutor();
for (int i=0; i<10; ++i)
ex.execute(test);
}
private static class Test implements Runnable {
// non volatile variable in question
private int state = 0;
@Override
public void run() {
// will we always see updated state value? Will updating state value
// guarantee future run's see the value?
if (this.state != -1)
this.state++;
}
}
对于上面的单线程执行器:
让 test.state 不可变可以吗?换句话说,每个连续的 Test.run()(这将按顺序发生而不是同时发生,因为执行程序也是单线程的),总是会看到更新的 test.state 值?如果不是,Test.run() 的退出是否确保本地线程所做的任何更改都被写回主内存?否则,如果不是在线程退出时,本地线程所做的更改何时会写回主内存?
最佳答案
只要它只是一个单线程,就没有必要让它变易变。如果你打算使用多线程,你不仅应该使用 volatile,还应该使用 synchronize。 递增数字不是原子操作 - 这是一个常见的误解。
public void run() {
synchronize (this) {
if (this.state != -1)
this.state++;
}
}
除了使用同步,您还可以使用 AtomicInteger#getAndIncrement() (如果您之前不需要 if)。
private AtomicInteger state = new AtomicInteger();
public void run() {
state.getAndIncrement()
}
关于java - 并发、对象可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1901789/