закидают камнями?
В целом решил почитать именно про JMM, и там такой пример
public class DekkerVolatile {
private volatile int x;
private volatile int y;
public void T1() {
x = 1;
int r1 = y;
}
public void T2() {
y = 1;
int r2 = x;
}
}
Говориться, что благодаря valatile мы достигаем синхронизированного порядка, и у нас при нескольких потоках с вызовом разных методов класса не может быть (r1, r2) = (0, 0). Однако насколько я понимаю volatile гарантирует атомарность записи и чтения, не даёт кешировать. Но компилятор и т.д. могут ведь поменять порядок действий в каждом методе и тогда (0,0) в моём понимании будет. Я просто тупо заперся и не могу осознать как это работает. Может кто сможет описать недостающее простыми словами?
https://habr.com/ru/articles/685518/
P.S.
Поменять дйствия компилятор может в моём понимании так как x = 1; int r1 = y; операции несвязанные например.
В приведённой статье как раз даётся ответ на ваш вопрос в секции Memory Ordering vs Instructions Ordering
хммм....не до конца понял....то есть volatile влияет безусловно на memory order не лишь в условиях атомарности чтения и записи в отношении кеширования и тяжёлых чисел к примеру, но и в более широком плане? Тобишь volatile даёт команду проанализировать порядок действий в разных методах, чтобы не изменился порядок записи-чтения....? Просто много где пишут, что volatile категорически не влияет на порядок действий же.....то что порядок инструкций подчиняется порядку памяти я осознаю, не понимаю как это тут отрабатывает....
или ты про то, что перестановка может произойти, однако позже будет выявлен конфликт, операция откатится и пройдёт заного уже правильно? "Если какое-то правило нарушается, то процессор возвращается к более раннему состоянию: результат чтения отбрасывается, а записи не коммитятся в память." про это имел ввиду?
HB достигается не только записью или чтением, а комбинацией запись/чтение, так что твой пример нерабочий
если ты про код, то он из статьи за счёт которой я пытаюсь начать вникать в многопоточку на более глубоком уровне, на уровне JMM. Он не будет работать так чтобы 2 потока запустились, каждый поток вызывает 1 из 2-х методов и никогда не будет (r1, r2) = (0, 0). Это левый пример в статье?
Вот тут есть наглядные таблицы: https://gee.cs.oswego.edu/dl/jmm/cookbook.html Порядок гарантируется между всеми инструкциями над volatile филдами в рамках 1 потока, даже если они независимы друг от друга
volatile не гарантирует атомарность записи/чтение и не про кэширование. volatile - это один из synchronization action'ов(который обычно выражается через fence, но может быть через что угодно), который образует synchronization order(вместе с другими спец.операциями), который с другими порядками + программой + read + write определяет абстрактное исполнение, и уже jmm определяет какие абстрактные исполнения имеют права на жизнь, а какие нет. И в данном случае, так как у нас появляется ребро happens-before(из synchronized+synchronzied with order'а), то такое абстрактно исполнение, которое приведет к (r1, r2) = (0, 0) должно быть запрещено. Но так как это private переменные и такое состояние non-observable, то оно вне контекста jmm, кмк.
cookbook не определяет JMM, он создан для людей, которые компиляторы пишут. Я вот в этом не уверен, но, кмк, так как это private переменные, оно вообще вне контекста JMM. P.S. не в рамках одного потока, а как раз между несколькими, именно это гарантирует synchronization with order, который вместе с program order определяет happens-before.
> volatile не гарантирует атомарность записи/чтение есть пример, когда запись/чтение volatile поля не атомарна?
Да, тут я неправильно сформировал, я имел в виду, что оно не про атомарность, так как атомарность уже гарантируется тем, что «чтение R видит значение V, записанное действием W». P.S. Поправил:)
Илья, непонятно откуда ты взял, что private поля "вне контекста jmm".
volatile кмк все-таки про атомарность тоже, когда речь идет о работе с лонгами и даблами, в jls17 об этом же даж отдельным пунктом написали
Поправил Илья, что это не только про атомарность записи и чтения
Все дело в том, что volatile привносит с собой очень много гарантий (например, в случае деккера еще очень важно и то, что операции по volatile-переменным глобально упорядочены, поэтому результат (0,0) противоречит sequential consistency)
Jls - это отдельно прописывает, но в семантике jmm запись лонг/дабл два отдельных action’а.
Если это non-observable состояние, то, кмк, jvm может делать все, что душе угодно, так как в любом случае будет удовлетворять любому абстрактному исполнению(а конкретно никакому), вероятно, реализация, конечно, не зависит от наличия модификатора доступа, но если отталкиваться только от семантики памяти, то, кмк, в этом есть смысл.
Определи что такое non-observable, пожалуйста. Далее, у volatile поля есть флаг ACC_VOLATILE, и требование только одно -- не может быть одновременно ACC_VOLATILE и АСС_FINAL. Далее, если я через reflection пишу и читаю это volatile поле, сделав его доступным -- все гарантии обязаны выполняться и выполняются.
Non-observable - это состояние, при котором никто не делает r/w-action’ы. Действительно, гарантии должны сохраняться, но если и через reflection никто не ходит и эксплицитно не делает r/w, то, так как такого исполнения программы нет, то JMM и не определяет, что его нужно удовлетворять. P.S. Это лично мои рассуждения, я уверен, что на практике оно так не работает, но если исходить только из алгебры исполнений, то, мне кажется, это имеет смысл. Вообще, мне просто наличие private’а в примере не понравилось, так как оно путает новичков.
Но JMM не использует sequential consistency…
Каким образом это можно понять? Когда я могу прям в рантайме генерить байткод, его грузить и его исполнять?
Ну это уже другой вопрос:) Я поэтому и сказал, что оно так не работает в реальности. Но если представить, что у нас есть возможность это определять, то в теории оно бы так и имплементировалось, модель памяти же не про имплементацию все-таки.
Как это не использует, когда этот термин в JLS 17 есть и используется. Тем более, не вижу ни одной причиной не пользоваться sq когда все переменные в примере с volatile.
«If we were to use sequential consistency as our memory model, many of the compiler and processor optimizations that we have discussed would be illegal.»
Обсуждают сегодня