Внутри Java синхронизированный статический метод: происходит до отношения для статической переменной

Гарантируется ли обновление статической переменной внутри синхронизированного метода класса раньше? Используйте это в качестве примера:

public class MyClass {
    private static boolean isDone = false;

    public static synchronized doSomething() {
        if (!isDone) {
            // ...
        }

        isDone = true;
    } 
}

Является ли переменная isDone (но не volatile) видимой для всех потоков после обновления внутри этого синхронизированного метода класса? Насколько я понимаю, синхронизация самого MyClass.class не гарантирует, что все обновления его статических переменных будут видны другим потокам, поскольку другие потоки могут иметь для этого локальный кеш.


person bohanl    schedule 01.07.2015    source источник
comment
очевидно, нет, т.к. чтения не синхронизируются на мониторе   -  person AdamSkywalker    schedule 01.07.2015
comment
в любом случае, для вашего примера это будет работать, если переменная будет использоваться только внутри синхронизированного метода   -  person AdamSkywalker    schedule 01.07.2015


Ответы (3)


происходит-прежде - это отношение между двумя событиями. Одно из событий, на которое вы указали: «обновление статической переменной внутри метода синхронизированного класса». Какое еще событие вы имеете в виду? Простое чтение этой переменной в другом потоке? Нет, простое чтение в другой теме не участвует в отношениях «происходит до».

То есть вы правы, предполагая, что синхронизация не гарантирует, что все обновления переменных будут видны другим потокам.

UPDT Чтобы гарантировать, что все обновления переменных видны другим потокам, эти потоки также должны синхронизировать свои чтения, то есть выполнять чтение внутри синхронизированного метода класса.

person Alexei Kaigorodov    schedule 01.07.2015
comment
Это то, что я думал ... но см. цитаты выше, которые я нашел. - person bohanl; 01.07.2015
comment
другое событие должно было считываться в другом потоке в синхронизированном методе - person bohanl; 01.07.2015
comment
цитата говорит, что мы приобретаем монитор. Другие потоки должны получить монитор, чтобы увидеть обновления. - person Alexei Kaigorodov; 01.07.2015
comment
Правильно.... поэтому, если другие потоки выполняют синхронизированный статический метод, они увидят самое обновленное значение, поскольку монитор одинаков для всех потоков. - person bohanl; 01.07.2015

Я нашел ответ здесь: https://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#synchronization

После выхода из синхронизированного блока мы освобождаем монитор, что приводит к сбросу кеша в основную память, чтобы записи, сделанные этим потоком, могли быть видны другим потокам. Прежде чем мы сможем ввести синхронизированный блок, мы получаем монитор, что приводит к аннулированию кэша локального процессора, так что переменные будут перезагружены из основной памяти. После этого мы сможем увидеть все записи, сделанные видимыми в предыдущем выпуске.

person bohanl    schedule 01.07.2015

Вот более простой способ думать об этом, который работает, если вы следуете хорошей практике кодирования:

Если это synchronized, вам не о чем беспокоиться.

Это связано с тем, что если поток A обновляет какую-либо переменную, а затем снимает блокировку, обновление будет видно потоку B после того, как поток B заблокирует ту же блокировку, и если вы следуете хорошей практике кодирования, то ваши synchronized блоки будет как можно меньше: вы не будете касаться каких-либо общих переменных внутри синхронизированного блока, которые не нуждаются в синхронизации. И, если вы следуете хорошей практике кодирования, каждый доступ к переменной (запись или чтение) будет синхронизирован.

person Solomon Slow    schedule 01.07.2015