通过 ThreadPoolExecutor.execute() 保证内存可见性

发布于 2024-12-15 12:04:46 字数 810 浏览 0 评论 0原文

如果您使用 ThreadPoolExecutor 执行 Runnable,并且此 Runnable 修改了某些共享状态,是否可以保证这些对共享状态的更改在提交可运行对象的原始线程中是否可见游泳池?假设只有 1 个共享状态的写入者和 1 个读取者。我知道,当您使用返回 FutureExecutorService 时,执行 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?
}

If you execute a Runnable with a ThreadPoolExecutor, and if this Runnable modifies some shared state, is there any guarantee as to whether these changes to the shared state will be visible in the original thread that submitted the runnable to the pool? Assume there's only 1 writer to shared state and 1 reader. I know that when you use the ExecutorService which returns a Future, doing a Future.get() will guarantee visibility.


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?
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

好菇凉咱不稀罕他 2024-12-22 12:04:46

这取决于情况,没有隐式保证状态更改将立即反映在原始线程中,主要是因为原始线程可能有一个 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

It depends, there is no implicit guarantee that the change in state will be immediately reflected in the original thread, primarily because the original thread may have a cached copy of the value of x that will not be updated when another thread changes the value of x in main memory.

You can work around this by adding an explicit guarantee using the volatile keyword, like:

class State {
    private volatile int x;
    public State(int y) { x = y; }
    public void setX(int y) { x = y; }
    public int getX() { return x; }
}

This tells the compiler that it cannot cache the value of x, and that every time the program reads x it must check the value that is in main memory. This will cause the original thread to see the new value of x as soon as any other thread modifies it.

More details here:

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

最美不过初阳 2024-12-22 12:04:46

几乎任何检测线程已完成其工作的明智方法(除了仅同步该一个变量的 volatile 之外)也将保证内存的同步视图。您的示例无法确保线程已完成,因此它显然不起作用。 C# 不提供任何特定的及时性保证,因此您不能使用 sleep 作为同步形式。

Pretty much any sane way to detect that the thread has finished its work (other than volatile which only synchronizes that one variable) will also guarantee a synchronized view of memory. Your example has no way to be sure the thread has finished, so it obviously won't work. C# doesn't provide any particular timeliness guarantees, so you can't use sleep as a form of sychronization.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文