LINUX.ORG.RU

Видимость изменений в Java. Простой вопрос

 


1

1

Предположим есть слудующий код.

Тред 2:

this.surface = new Surface(surf_texture);
// initialized_s - это Object()
synchronized (this.initialized_s) {
    this.initialized_s.notify();
}

Тред 1:

thread.start();
synchronized (thread.initialized_s) {
    while (thread.surface == null) {
        try {thread.initialized_s.wait();} catch (InterruptedException e) {}
    }
}

Насколько я понимаю, нет никаких гарантий, что изменения переменной surface будут когда-нибудь видны. Когда мы вернемся из wait(), мы будем видеть null. Далее (т.к. мы тестируем в цикле) мы зайдем в wait() еще раз. Но т.к. это был настоящий wake-up, вызванный notify(), то второго notify() уже не будет. Насколько я понимаю, далее wait() снимет блокировку, снова переведет тред в сон и мы так и останемся на этом месте.

Вопросы:

1) Как это починить?

2) Хотелось указание на раздел/главу/страницу авторитетного источника, где говорится, что такой-то и такой-то способ точно дает гарантию.



Последнее исправление: entemophyllon (всего исправлений: 2)

Есть догадка: перенести присвоение this.surface = внутрь synchronized. Но, из синтаксиса не следует, что происходящее с некой ссылой B в блоке synchronized взятым от другой ссылки A должно стать видно остальным именно в тот момент как это следует из текста программы. Это всего лишь слабая догадка. Посему прошу пояснений.

entemophyllon
() автор топика

Насколько я понимаю, нет никаких гарантий, что изменения переменной surface будут когда-нибудь видны. Когда мы вернемся из wait(), мы будем видеть null.

Возврат из wait == захвату лока, а захват лока синхронизируется с его освобождением в треде 2. И видит все изменения до освобождения лока, в т.ч. создание объекта.

Откуда null?

anonymous
()
Ответ на: комментарий от anonymous

И видит все изменения до освобождения лока, в т.ч. создание объекта.

Видит изменения, случившиеся с какой по какую строку? И с чего бы вдруг вообще? Я так понимаю, что в джаве, что бы изменения 100% гарантировано отразились во другом треде в данном примере чего-то не хватает.

entemophyllon
() автор топика
Ответ на: комментарий от entemophyllon

Видит изменения, случившиеся с какой по какую строку?

Любые до анлока.

И с чего бы вдруг вообще?

https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.4
https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5

Я так понимаю, что в джаве, что бы изменения 100% гарантировано отразились во другом треде в данном примере чего-то не хватает.

Ок, перенеси создание объекта под лок.

anonymous
()
Ответ на: комментарий от anonymous

Я вот начал бегло читать JSL гл.17. Запутался окончательно.

Насколько я понимаю, synchronization actions гарантированно будут выстроены относительно друг-друга по программному порядку (program order = total order = sequentially consistent). Но к обычным действиям это не относится (они могут быть реодерены как угодно лишь бы это не было видно intra-thread, если я правильно понял).

Кажется, что ограничений на реордеринг synchronization action (к таковы относится взятие лока) относительно обычного action (запись в переменную, например) нет. Соотв. нет гарантии того, что не будет произведен следующий реордеринг:

this.surface = new Surface(surf_texture);
synchronized (this.initialized_s) { this.initialized_s.notify();}
synchronized (this.initialized_s) { this.initialized_s.notify();}
this.surface = new Surface(surf_texture);
entemophyllon
() автор топика

Вопрос закрыт. Какие гарантии на «НЕреордеринг» даются, как сбрасываются процессорные кеши в память и как они перечитываются доходчиво и простыми словами объясняется тут:

http://gee.cs.oswego.edu/dl/cpj/jmm.html

http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html

так же полезно:

https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5

http://www.cs.umd.edu/~pugh/java/memoryModel/issues.pdf

entemophyllon
() автор топика
Ответ на: комментарий от entemophyllon

synchronization actions гарантированно будут выстроены относительно друг-друга по программному порядку (program order = total order = sequentially consistent).

sequentially consistent это когда есть total order для всех действий всех потоков. Какой может быть program order для действий в разных потоках, выполняющих разный код?

program order в одном потоке согласован с total order, но равенства тут нет.

Соотв. нет гарантии того, что не будет произведен следующий реордеринг:

Есть. Такой реордеринг сломает happens-before.

anonymous
()
Ответ на: комментарий от entemophyllon

как сбрасываются процессорные кеши в память и как они перечитываются доходчиво и простыми словами объясняется тут

Разве в Java Memory Model используется понятие «кеша»?

anonymous
()
Ответ на: комментарий от anonymous

Разве в Java Memory Model используется понятие «кеша»?

В разъяснениях как у Brian Goetz так и Doug Lea эффекты синхронизации объясняются или явно через «local processor cache» или с ипользованием терминов «working memory employed by the thread», «flush» и «reload». Выяснять имел ли Goetz под «working memory employed by the thread» то же самое, что Lea имел ввиду под «cache» я не собираюсь т.к. мне не нужно. Так же как выяснять не имели ли они оба ввиду регистры (по отношении к которым JLS использует «cached in»). Мне достаточно того что оба эти термина служат объяснением эффекта от одного и того же действия, но в разных статьях. Явного концепта процессорного кешей в JLS нет (наверное потому, что спецификации не важно какие у конкретной имплементации железные и софтовые детали). JSR133 я не открывал и не собиаюсь - мне нужно писать корректную, не глючащую программу на жаве - языке с которым я ранее никогда не работал. Надеюсь ответил на твой вопрос.

entemophyllon
() автор топика
Ответ на: комментарий от anonymous

Ты прав, я совершенно запутался.

После

A synchronization order is a total order over all of the synchronization actions of an execution. For each thread t, the synchronization order of the synchronization actions in t is consistent with the program order of t.

Я решил, что чтобы вникнуть в это все мне понадобится сильно больше времени чем я собирался на это потратить.

Спасибо за попытки объяснить мне что-то.

entemophyllon
() автор топика
Ответ на: комментарий от entemophyllon

Добавлю, я нашел ответ на свой частный конкретный вопрос, что устроило меня.

entemophyllon
() автор топика
Ответ на: комментарий от entemophyllon

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

entemophyllon
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.