Видимость памяти гарантирует с ThreadPoolExecutor.execute () - PullRequest
2 голосов
/ 16 ноября 2011

Если вы выполняете Runnable с ThreadPoolExecutor, и если этот Runnable изменяет некоторое общее состояние, есть ли какая-либо гарантия того, будут ли эти изменения общего состояния видны в исходном потоке, который передал runnable в пул ? Предположим, что есть только 1 писатель в общее состояние и 1 читатель. Я знаю, что когда вы используете ExecutorService, который возвращает 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?
}

Ответы [ 2 ]

5 голосов
/ 16 ноября 2011

Зависит от того, что не существует явной гарантии того, что изменение состояния будет немедленно отражено в исходном потоке, в первую очередь потому, что исходный поток может иметь кэшированную копию значения 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

1 голос
/ 16 ноября 2011

Практически любой разумный способ обнаружить, что поток завершил свою работу (кроме volatile, который синхронизирует только одну переменную), также гарантирует синхронизированное представление памяти.В вашем примере нет способа убедиться, что поток завершен, поэтому он явно не будет работать.C # не предоставляет каких-либо конкретных гарантий своевременности, поэтому вы не можете использовать sleep как форму синхронизации.

...