如果您使用 ThreadPoolExecutor
执行一个 Runnable,并且如果这个 Runnable 修改了一些共享状态,是否可以保证这些对共享状态的更改是否在提交的原始线程中可见可运行到游泳池?假设共享状态只有 1 位作者和 1 位读者。我知道当您使用返回 Future
的 ExecutorService
时,执行 Future.get()
将保证可见性。
class State {
private int x;
public State(int y) { x = y; }
public void setX(int y) { x = y; }
public int getX() { return x; }
}
main() {
threadPool = new ThreadPoolExecutor(8, 16, 100, TimeUnit.SECONDS, new ArrayBlockingQueue(...))
final State myState = new State(1);
threadPool.execute(new Runnable() {
public void run() {
myState.setX(50);
}
});
while (true) {
if (myState.getX() == 50) {
break;
}
sleep();
} // would this loop terminate?
}
最佳答案
这取决于,没有隐含的保证状态的改变会立即反射(reflect)在原始线程中,主要是因为原始线程可能有 x
值的缓存副本,它不会当另一个线程更改主内存中 x
的值时被更新。
您可以通过使用 volatile
关键字添加显式保证来解决此问题,例如:
class State {
private volatile int x;
public State(int y) { x = y; }
public void setX(int y) { x = y; }
public int getX() { return x; }
}
这告诉编译器它不能缓存 x
的值,每次程序读取 x
时它都必须检查主内存中的值。这将导致原始线程在任何其他线程修改它时立即看到 x
的新值。
更多细节在这里:
http://www.javamex.com/tutorials/synchronization_volatile.shtml
关于java - ThreadPoolExecutor.execute() 的内存可见性保证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8146218/