Происходит до и изменчивая переменная

Ниже приведены всего три правила JMM «случается до». Я не перечисляю другие правила, так как мой вопрос касается только этих трех правил.

  • Правило блокировки монитора. Разблокировка блокировки монитора происходит перед каждой последующей блокировкой той же блокировки монитора.
  • Правило начала потока. Вызов Thread.start в потоке происходит перед каждым действием в запущенном потоке.
  • Правило прерывания. Поток, вызывающий прерывание в другом потоке, происходит до того, как прерванный поток обнаружит прерывание (либо путем создания InterruptedException, либо путем вызова isInterrupted или interrupted).

Вопросы

  1. 1-й вопрос правила. Предположим, что два потока A и B имеют синхронизированные блоки кода. Означает ли первое правило, что любая переменная, установленная в синхронизированном блоке в потоке A, будет видна коду в синхронизированном блоке потока B, даже если переменная НЕ объявлена ​​как volatile?

  2. Второй вопрос правила. Допустим, поток A запускает поток B. Означает ли второе правило, что любая переменная, установленная в родительском потоке перед вызовом start(), будет видна потоку B, даже если переменная НЕ объявлен как изменчивый?

  3. 3-й вопрос правила. Допустим, поток A прерывает поток B. Означает ли третье правило, что любая переменная, установленная в потоке A до прерывания потока B, будет видна потоку B после обнаружения прерывания, даже если переменная не объявлена ​​как volatile?

Наконец, еще один вопрос:

  1. В документации BlockingQueue сказано:
    #P7#

Означает ли это, что любая переменная, установленная в потоке A перед помещением объекта в очередь блокировки, будет видна потоку B после удаления объекта из очереди, даже если переменная НЕ объявлена ​​как volatile?

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


person Saptarshi Basu    schedule 01.09.2015    source источник
comment
4 х Да. Это один и тот же вопрос, повторенный четыре раза. Но забудьте о картинке сброса памяти, это неправильно. Пишет видно, конец истории.   -  person Marko Topolnik    schedule 01.09.2015
comment
Рекомендация — книга «Java Concurrency in Practice».   -  person hemant1900    schedule 01.09.2015


Ответы (1)


1-й вопрос правила. Допустим, два потока A и B имеют синхронизированные блоки кода.

В потоках нет имеющих кода. Потоки выполняют код.

Означает ли первое правило, что любая переменная, установленная в синхронизированном блоке в потоке A, будет видна коду в синхронизированном блоке потока B, даже если переменная НЕ объявлена ​​как volatile?

Да, предположим, что у нас есть:

private int i;
private final Object lock = new Object();

void foobar(...) {
    ...
    synchronized(lock) {
        i = ...;
    }
}

int getI() {
    synchronized(lock) {
        return i;
    }
}

Если поток A вызывает foobar(), а затем поток B впоследствии вызывает getI(), то поток B получит новое значение i.

Но заметьте! В моем примере выше нет способа доказать, какой вызов действительно произошел первым. Если ваша программа зависит от того, что эти вызовы происходят в определенном порядке, то ей потребуется больше, чем просто мьютекс: ей потребуются некоторые средства, чтобы сделать поток B wait() для потока A, чтобы выполнить обновление.


Второй вопрос правила. Допустим, поток A запускает поток B. Означает ли второе правило, что любая переменная, установленная в родительском потоке перед вызовом start(), будет видна потоку B, даже если переменная НЕ объявлена ​​как volatile?

Да, вот что это значит.

3-й вопрос правила...

Да снова.

  1. ... Блокирующая очередь ...

Да снова.


... Через приведенные выше вопросы я пытаюсь понять, происходит ли сброс памяти после этих событий, так что...

Даже не думайте о "очистке памяти". Это не является частью языка Java: если это происходит, то это детали реализации, и вам не нужно об этом беспокоиться, если только вы не реализуете JVM.

Единственная концепция, о которой вам нужно беспокоиться, это «происходит раньше».

Всякий раз, когда JLS говорит, что A происходит до B, это означает, что если A происходит в потоке 1, а B происходит в потоке 2, и вы можете доказать, что A действительно произошло до B в режиме реального времени, то любое поле, которое было обновлено потоком 1 до того, как произошло A, будет гарантированно отображаться в потоке 2 после того, как произойдет B.

person Solomon Slow    schedule 01.09.2015