Thread 1 | Thread 2 |
---|---|
volatile int va; | |
va = 10; | int b = va; |
Вопросы (отвечать желательно по порядку, не забегая вперед):
- Какие здесь есть межпоточные ребра HB?
- Может ли в
b
оказаться что-то, кроме 10? - Может ли в
b
оказаться 0? - Изменится ли что-либо, если здесь заменить
volatile store
наlazySet
?
Хм. На мой взгляд, должно быть так:
ОтветитьУдалить1. Здесь есть два ребра hb, порожденные отношением synchronized-with по инициализации переменной 'va', которое должно произойти до первой операции в Thread-1 и Thread-2, соответственно. Кроме того, есть ещё одно ребро hb, которое связывает чтение из va и запись в b (согласно program order). Ну, и транзитивное ребро hb, между начальной инициализацией va и записью в b.
2. Может.
3. Может.
4. В контексте данного примера - ничего.
Этот комментарий был удален автором.
ОтветитьУдалить1. write(va = 0) hb write(va = 10); write(va = 0) hb read(va = 0); write(va = 10) hb read(va = 10);
ОтветитьУдалить2. Может, что угодно, при условии, что в это поле кто-то где-то писал. Если нет, то тоже может, но только 0 и 10.
3. Может.
4. Ничего. Равно как и отсутствие volatile вообще.
@aleksey
ОтветитьУдалить-- А... А, это вы, Штирлиц... Идите, и не мешайте работать!
Нужно было дописать в конце для тебя. А то пришел, и сразу всю интригу поломал :)
@aleksey
ОтветитьУдалитьНо-таки отсутствие volatile вообще что-то поменяет - межпоточных ребер hb уже не будет. А?
@Lerm
Я из вашего ответа не очень понял -- _меж_поточные ребра-то есть?
Вы не написали в каком порядке физически происходят
ОтветитьУдалить'va = 10' и 'vb = va'. Так вполне возможен такой порядок:
1. vb = va
2. va = 10
тогда в vb будет 0.
Но если они произошли в таком порядке:
1. va = 10
2. vb = va
То при наличии volatile в vb может быть только 10, а если lazySet, то в vb могут быт и 10, и 0.
Как-то так.
@artem
ОтветитьУдалитьВ примере нет vb -- есть просто b, и это просто локальная переменная, она не волатильна.
@ Ruslan
ОтветитьУдалить> Я из вашего ответа не очень понял -- _меж_поточные ребра-то есть?
Ну, по моему пониманию, в данном фрагменте кода (по той информации, которая дана) -- нет. Поскольку порядок синхронизационных действий по записи/чтению va не определен для произвольного исполнения, то межпоточного ребра для него нет.
столько комментов и все разные ответы...
ОтветитьУдалитьтак какой ответ правильный?
Хорошее приближение к условно правильному ответу дал Алексей. Главный поинт в том, что порядки HB/SW/SO являются атрибутом конкретного сценария исполнения, а не кода вообще.
УдалитьТут выше написали, что volatile можно убрать, и ничего от этого не изменится, разве это так ? volatile обеспечивает атомарность операций и является synchronization action, поэтому порядок выполнения будет либо (1) и потом (2), либо наоборот, причем в случае, когда первым выполнится write, read будет дополнительно связан с ним отношением happens-before (write hb read). Если же volatile убрать, то никаких гарантий на то, что будет получено в результате чтения - не будет, это будет чтение по data race. И программа станет некорректно синхронизированной, в отличие от текущего случая с volatile, когда программа синхронизирована корректно. Или я не прав, и действительно разницы нет ?
ОтветитьУдалить