Re[12]: volatile
От: Golovach Ivan Украина http://kharkovitcourses.blogspot.com
Дата: 03.10.09 12:23
Оценка:
Здравствуйте, denis.zhdanov, Вы писали:

DZ>Здравствуйте, Golovach Ivan, Вы писали:


GI>>МММ ... Я еще раз пересмотрел 17-ю главу jls.third_edition [http://java.sun.com/docs/books/jls/third_edition/html/memory.html] и не обнаружил правила запрещающего следующее:

GI>>Пусть один поток вызывает метод doIt() у общего объекта
GI>>
GI>>class Shared {
GI>>    public volatile int vol = 0;
GI>>    public int nonvol = 0;
GI>>    public void doIt() {
GI>>        vol = 1;
GI>>        nonvol = 1;
GI>>    }
GI>>}
GI>>

GI>>а второй поток проверяет условие у этого же общего объекта
GI>>
GI>>Shared shared = ... 
GI>>if (shared.vol == 0 && shared.nonvol == 1) {...}
GI>>

GI>>и, как я понимаю, это условие МОЖЕТ ВЫПОЛНИТСЯ. Т.е. с точки зрения второго потока будет виден реордеринг записи vol и записи nonvol.
GI>>Для себя я понял JMM так, что нельзя нарушать happend-before и casuality. Оно и не нарушается в данном примере.
GI>>Вполне допускаю, что я не прав. Но тогда я заблуждаюсь искренне.
GI>>Вы могли бы обосновать свое мнения на моем примере основываясь на спецификации языка?

DZ>В приведенном примере указанное условие может выполниться не из-за reordering, а из-за обыкновенного race condition. Т.е. последовательность событий может быть такая:


DZ>

    DZ>
  1. Thread t1 calls doIt();
    DZ>
  2. Thread t2 checks 'shared.vol == 0 (true)';
    DZ>
  3. t1 executes 'vol = 1; nonvol = 1';
    DZ>
  4. t2 checks 'shared.nonvol ==1 (true)';
    DZ>
Согласен. Предлагаю переформулировку. Мне кажется, что переписанное условие
if (shared.nonvol == 1 && shared.vol == 0) {...}
может выполнится. По крайней мере, я не нашел запрета на это, но нашел подтверждение в виде Roach Motel Principle.
И если это так, что с точки зрения второго потока он будет наблюдать явление, трактуемое как реордеринг записи в vol и nonvol. Т.е. то, что категорически отвергал remark.

DZ>В указанном примере happen-before вообще не работает, потому что 'nonvol = 1' выполняется после записи в volatile-переменную.

Ну да, хаппенд-бефора тут нет. Вопрос же был — возможен ли хоть какой-то реордеринг волатайл и не-волатайл операций.

Собственно, я опираюсь на Roach Motel Principle (тут, например — http://osdir.com/ml/java.jsr.166-concurrency/2008-04/msg00018.html — Автор Джереми Мэйсон):
""Roach Motel" applies to synchronized blocks -- instructions can move
into them, but not out. So, normal accesses can be moved from after a
monitorexit to before it, and from before a monitorenter to after it.
That's the roach motel principle.

The same reasoning applies to volatiles under the assumption that a
volatile write is "the same" as a monitorexit and that a volatile read
is "the same" as a monitorenter.

So, your answer is that you *can* move normal accesses that occur after
a volatile write to before it."

З.Ы. по Roach Motel Principle есть несколько постов на concurrency-interest (надо искать по всему архиву, но вот навскидку — http://www.cs.umd.edu/~pugh/java/memoryModel/archive/0773.html).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.