使用ThreadPoolExecutor.execute()保证内存可见性

Har*_*ish 2 java multithreading jvm thread-safety

如果使用a执行Runnable ThreadPoolExecutor,并且如果此Runnable修改了某些共享状态,是否可以保证在将可运行的池提交到池的原始线程中是否可以看到对共享状态的这些更改?假设只有一个作家共享州和一个读者.我知道当你使用ExecutorService它返回a时Future,做一个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?
}
Run Code Online (Sandbox Code Playgroud)

aro*_*oth 5

这取决于,没有隐含的保证状态的更改将立即反映在原始线程中,主要是因为x当另一个线程更改xmain中的值时,原始线程可能具有该值的缓存副本将不会更新记忆.

您可以通过使用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; }
}
Run Code Online (Sandbox Code Playgroud)

这告诉编译器它无法缓存值x,并且每次程序读取x它时都必须检查主内存中的值.这将导致原始线程在x任何其他线程修改它时立即查看新值.

更多细节在这里:

http://www.javamex.com/tutorials/synchronization_volatile.shtml