powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Reordering
83 сообщений из 83, показаны все 4 страниц
Reordering
    #38524479
zig zu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
есть такой код

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
    //first thread  
    reslit = calc();  
    reslitReady = true;
      
    //second thread  
    if (reslitReady){  
        takeDesision(reslit);  
    }  



в первом потоке может случится реордеринг и второй поток словит NPE. Как сделать, чтобы первый поток всегда выполнял строку
Код: plaintext
reslitReady = true
после строки
Код: plaintext
reslit = calc();
? В противном случае от NPE во втором потоке никто не гарантирует.
...
Рейтинг: 0 / 0
Reordering
    #38524496
Лагман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: java
1.
reslitReady = reslit != null 
...
Рейтинг: 0 / 0
Reordering
    #38524510
zig zu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Лагман
Код: java
1.
reslitReady = reslit != null 



И?
Сначала выполнится reslitReady = reslit != null, потом reslit = calc(); и второй поток будет вечно ждать.
...
Рейтинг: 0 / 0
Reordering
    #38524518
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
volatile?
...
Рейтинг: 0 / 0
Reordering
    #38524522
zig zu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowiczvolatile?

Каким образом volatile спасет от reordering?
...
Рейтинг: 0 / 0
Reordering
    #38524526
Лагман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zu,

реордеринг возможен, если инструкции независимы друг от друга. Если мы пишем reslit != null то это уже зависит от reslit, и реордеринга не будет.
...
Рейтинг: 0 / 0
Reordering
    #38524532
Лагман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Этот пост раскручиваете? http://www.javaspecialist.ru/2011/06/java-memory-model.html
...
Рейтинг: 0 / 0
Reordering
    #38524534
zig zu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Лагманzig zu,

реордеринг возможен, если инструкции независимы друг от друга. Если мы пишем reslit != null то это уже зависит от reslit, и реордеринга не будет.

Согласен, так наверное будет работать.

Давайте тогда усложним задачу ))

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
 //first thread  
    calc();  
    reslitReady = true;
      
    //second thread  
    if (reslitReady){  
        takeDesision();  
    } 
...
Рейтинг: 0 / 0
Reordering
    #38524536
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zuBlazkowiczvolatile?

Каким образом volatile спасет от reordering?
Если ты пришёл в форум за вопросом - то должен
соблюдать протокол. Тебе задали вопрос - ответь на него.
Если ты сам задаёшь вопросы - то сообщество решит
что ты слишком умён и тебе помогать не стоит.
...
Рейтинг: 0 / 0
Reordering
    #38524539
zig zu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ЛагманЭтот пост раскручиваете? http://www.javaspecialist.ru/2011/06/java-memory-model.html

Нет, я его прочитал и не понял момент про который спрашиваю.
...
Рейтинг: 0 / 0
Reordering
    #38524542
Лагман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Теперь calc() в экспшен засунуть
...
Рейтинг: 0 / 0
Reordering
    #38524553
Лагман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну, т.е. в try-catch
...
Рейтинг: 0 / 0
Reordering
    #38524558
zig zu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Лагманну, т.е. в try-catch

в этом случае тоже реордеринга не будет? ну то есть если calc будет в try-catch а после этой конструкции установвка флага?
...
Рейтинг: 0 / 0
Reordering
    #38524569
Лагман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zu,

На самом деле я не знаю, может гуру многопоточности подскажут
...
Рейтинг: 0 / 0
Reordering
    #38524630
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЛагманЭтот пост раскручиваете? http://www.javaspecialist.ru/2011/06/java-memory-model.html
Кстати, там же есть ссылка https://blogs.oracle.com/vmrobot/entry/модель_памяти_java , которая и является первоисточником всех статей выше, с изменененными примерами и прочей водой.

zig zuBlazkowiczvolatile?

Каким образом volatile спасет от reordering?

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

Так что подойдет для двух случаев.
...
Рейтинг: 0 / 0
Reordering
    #38524670
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лагман
Код: java
1.
reslitReady = reslit != null

Это не работает. Во-первых, это не защищает от реордеринга, так как те же спекулятивные чтения никто не отменял. Во-вторых, потому что если бы вы даже смогли таким образом предовтратить реордеринг, у вас все равно не будет гарантий того, что другой поток увидит изменения именно в таком порядке. Погуглите про store buffer и invalidate queue.
...
Рейтинг: 0 / 0
Reordering
    #38524675
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лагманzig zu,
реордеринг возможен, если инструкции независимы друг от друга. Если мы пишем reslit != null то это уже зависит от reslit, и реордеринга не будет.К сожалению, это не так. Out-of-order execution это значительно более сложная вещь, чем "раз зависимы, значит не зареордерятся".
...
Рейтинг: 0 / 0
Reordering
    #38524677
zig zu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
0FD,

Отлично! volatile спасет мир.
...
Рейтинг: 0 / 0
Reordering
    #38524684
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zuесть такой код

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
    //first thread  
    reslit = calc();  
    reslitReady = true;
      
    //second thread  
    if (reslitReady){  
        takeDesision(reslit);  
    }  



в первом потоке может случится реордеринг и второй поток словит NPE. Как сделать, чтобы первый поток всегда выполнял строку
Код: plaintext
reslitReady = true
после строки
Код: plaintext
reslit = calc();
? В противном случае от NPE во втором потоке никто не гарантирует.Вам нужен synchronized-with между запись в reslitReady, и чтением из него. Есть множество вариантов, как сделать это.
1) Самый простой - объявить reslitReady volatile.
2) Можно обернуть эти два участка кода в synchronized на одном и том же мониторе.
3) Ну и всевозможные способы, производные от первых двух.
...
Рейтинг: 0 / 0
Reordering
    #38524699
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще, мужики, потерпите, ждать осталось не долго - скоро будет готова моя первая часть тренинга по multithreading. В эту часть войдет вся теория по JMM, synchronized, volatile, final, а так же вопросы остановки потоков. Вчера как раз весь день рисовал схемки, как кэши работают :-)
Можете уже бронировать места
...
Рейтинг: 0 / 0
Reordering
    #38524721
Лагман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvВообще, мужики, потерпите, ждать осталось не долго - скоро будет готова моя первая часть тренинга по multithreading. В эту часть войдет вся теория по JMM, synchronized, volatile, final, а так же вопросы остановки потоков. Вчера как раз весь день рисовал схемки, как кэши работают :-)
Можете уже бронировать места

Тренинг будет выглядеть так: "Погуглите про ... " ?
...
Рейтинг: 0 / 0
Reordering
    #38524742
zig zu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cdtyjvЛагманzig zu,
реордеринг возможен, если инструкции независимы друг от друга. Если мы пишем reslit != null то это уже зависит от reslit, и реордеринга не будет.К сожалению, это не так. Out-of-order execution это значительно более сложная вещь, чем "раз зависимы, значит не зареордерятся".

Наверное Out-of-order execution действительно крутая и очень сложная штука, но не могли бы вы на пальцах объяснить, как вот такой код может подвергнутся реордеренгу?

Код: java
1.
2.
reslit = calc();
reslitReady = reslit != null  



с учетом того, что основное правило реордеренга гласит - после реордеринга поведение программы не должно меняться.
...
Рейтинг: 0 / 0
Reordering
    #38524751
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zuс учетом того, что основное правило реордеренга гласит - после реордеринга поведение программы не должно меняться.
Вероятно имеется ввиду, не то что могут поменять местами строки Java кода. А более мелкие операции уровня как байт-кода так и нативного после JIT компиляции.
...
Рейтинг: 0 / 0
Reordering
    #38524777
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zuНаверное Out-of-order execution действительно крутая и очень сложная штука, но не могли бы вы на пальцах объяснить, как вот такой код может подвергнутся реордеренгу?Например, speculative branch prediction. Как это может произойти:
1) Процессор начинает выполнять calc(), и натыкается там на чтение значения, которого нет в кэшах.
2) Из-за этого процессор вынужден отправить запрос в память на получение этого значения; длительность этого чтения может составлять сотни тактов.
3) Что бы не стоять эти такты без дела, процессор начинает фигачить следующие инструкции (пошел out-of-order execution);
4) Процессор натыкается "reslitReady = reslit != null"
5) Вроде бы дело дрянь, так и так придется ждать окончание долго чтения в calc(). Но процессор находит выход: он делает спекулятивное предположение, что, например, reslit != null в будущем будет true, и присваивает reslitReady = true.
6) Далее, если у вас есть что-то вроде "if (reslitReady) { ... }", процессор попытается спекулятивно выполнить какие-то инструкции из этого бранча.
7) Наконец, нам приходит ответ на чтение. Если процессор угадал результат - все круто, идем дальше. Если не угадал - откатываемся.
...
Рейтинг: 0 / 0
Reordering
    #38524790
zig zu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
cdtyjv,

а вот в тот момент, когда процессор начал заниматься предсказаниями и выполнил одно из них "присваивает reslitReady = true", это вот предсказанное значение уже может увидеть второй поток?
...
Рейтинг: 0 / 0
Reordering
    #38524809
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zuа вот в тот момент, когда процессор начал заниматься предсказаниями и выполнил одно из них "присваивает reslitReady = true", это вот предсказанное значение уже может увидеть второй поток?Теоретически - да. Как это работает на практике в конкретном процессоре - хз.
Как бы то ни было, вам, как для Java-разработчику, должно быть пофиг на то, из-за чего именно один поток видит изменения не в том порядке. Это может быть компилятор (напр. http://preshing.com/20120625/memory-ordering-at-compile-time/#out-of-thin-air), это может быть процессор, это могут быть застрявшие в store buffer значения, и т.д. Разбираться в этой кухне особого смысла нет.
Вас должен волновать сам факт того, что это возможно. Когда пишете многопоточные программы, всегда исходите из следующего предположения:
ПравилоЕсли у меня есть переменная, с которой работают несколько потоков, и один из них в нее пишет, то в отсутствие synchronized-with отношений другие потоки могут увидеть в этой переменной непредсказуемое значение.Это может быть устаревшее значение. Это может быть текущее значение. Это может быть ни то ни другое, а вообще какая-то полная хрень. Не важно. Важно то, что вы не можете на это значение полагаться.
...
Рейтинг: 0 / 0
Reordering
    #38525008
Alexey Tomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zucdtyjv,

а вот в тот момент, когда процессор начал заниматься предсказаниями и выполнил одно из них "присваивает reslitReady = true", это вот предсказанное значение уже может увидеть второй поток?

Есть два способа написания параллельных программ в java.

1. Учите JMM и строго следуете ей. Если сказано "порядок гарантируется с помощью synchronized или volatile"- значит используете.

2. Пытаетесь предсказать логику runtime-компилятора и надеетесь, что угадали верно.

Второй подход может и сэкономит пару тактов за час. Но когда стрельнёт- ошмётки мозгов долго будут соскребать со стенки.
...
Рейтинг: 0 / 0
Reordering
    #38527463
J.Serge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На мой взгляд reordering чуть-чуть демонизируется.
Строки и инструкции java-кода одного Thread'а при исполнении никогда физически не меняются местами, а выполняются одна за другой. Компилятор, интерпретатор, JIT-компилятор и прочие процессоры могут чутка видоизменить код, например, заменить конкатенацию строк, убрать ненужный synchronized, заменить вызов метода на inline-код или даже поменять местами команды процессора.
Но результат (после выполнения каждой инструкции) будет 100% идентичен последовательному выполнению инструкций java-кода.

По приведенной выше ссылке:
http://www.javaspecialist.ru/2011/06/java-memory-model.html ..
Тут еще важно отметить, что для выполнения операций в рамках одного потока, спецификация JVM разрешает делать только такой reordering, который приводит к абсолютно тем же результатам, если бы все операции выполнялись в порядке указанном в исходном коде с точки зрения потока, в котором этот код выполняется. Т.е. в одном потоке reordering никогда не проявляется.
..

Список операций связанных отношением happens-before:
..
В рамках одного поток любая операция happens-before любой операцией следующей за ней в исходном коде
..


И еще по другой приведенной выше ссылке:
https://blogs.oracle.com/vmrobot/entry/модель_памяти_java ..
Существует несколько основных правил для отношения 'происходит раньше':
..
в одном потоке любое действие происходит раньше любого действия, указанного в программе позже (т.е. с точки зрения потока его
действия выполняются в порядке, указанном в программе)
..


И первоисточник:
JSR-133: JavaTM Memory Model and Thread Specification..
Happens-Before Relationship:
..
Each action in a thread happens before every subsequent action in that thread
..


(И никакой out-of-order execution не повлияет на это. Это проблемы процессора. Если он отработал что-то напрасно, исходя из ложного предположения, то пусть сам и расхлебывает это: откатывается, перенакатывается - java-разработчика это не касается).

Reordering вообще вводится и рассматривается лишь как результат взаимодействия двух Thread'ов.
Reordering при выполнении строк одного Thread'а возможен только с точки зрения стороннего Thread'а - наблюдателя.
Типа наблюдатель может увидеть результат выполнение Thread'ом некой строки кода ПОСЛЕ того, как тот же наблюдатель увидит результат выполнение этим Thread'ом последующей строки кода.

И все. Чтобы избежать такого виртуального reordering'а, надо следовать приведенным уже до меня правилам. Они простые.
...
Рейтинг: 0 / 0
Reordering
    #38527511
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"В этой нитке" - да. А вот если ниток больше одной и они хоть как-то взаимодействуют ...
Возможны ньюансы, в общем. И чем больше ниток с ядрами, их исполняющими - тем суровее будут ньюансы.

P.S. На моём домашнем Sempron (не X2) будет корректно работать куча кода, которая начнёт сбоить на каком-нибудь X2 или, там, Core Duo.
...
Рейтинг: 0 / 0
Reordering
    #38527538
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zucdtyjvпропущено...
К сожалению, это не так. Out-of-order execution это значительно более сложная вещь, чем "раз зависимы, значит не зареордерятся".

Наверное Out-of-order execution действительно крутая и очень сложная штука, но не могли бы вы на пальцах объяснить, как вот такой код может подвергнутся реордеренгу?

Код: java
1.
2.
reslit = calc();
reslitReady = reslit != null  



с учетом того, что основное правило реордеренга гласит - после реордеринга поведение программы не должно меняться.
Такого не может быть такого т.к. out-of-order execution не может нарушить data-dependency.
Хотя тут видимо вообще в термин OOOE какой-то иной смысл вкладывается т.к. всегда это было такое архитектурное решение, которое позволяло выполнять несколько инструкций, если они не требовали одного и того же функционального юнита и не имели зависимостей по данным.
...
Рейтинг: 0 / 0
Reordering
    #38527544
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovА вот если ниток больше одной и они хоть как-то взаимодействуют
ну дак, они взаимодействуют по контракту. Не абы как пришлось.
Либо критическая секция тормозит поток, либо режьте куски БЛ без взаимодействия.
Иначе теряется смысл параллельной обособленной работы потока.
...
Рейтинг: 0 / 0
Reordering
    #38527548
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
J.SergeНа мой взгляд reordering чуть-чуть демонизируется.

+1 Точно подмечено.

В ситуации отсутствия гонок весь этот сферический "реордеинг" в вакууме может быть исключительно результатом операций, которые допустимы конкретной для железки с поправкам на JMM*. А когда гонки есть, то JMM никаких детерминированных сценариев выполнения не гарантирует.

Евангелие от Джеймса Гослинга 17.4.3 If a program has no data races, then all executions of the program will appear to be sequentially consistent.


* Это отягощается тем, что тестов JMM под разные классы железяк не существует наверное вообще т.к. вопрос "а не написать ли нам такое?" был поставлен лишь во второй половине в прошлого года. Так что приятного кодирования на экзотических архитектурах
...
Рейтинг: 0 / 0
Reordering
    #38527550
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaТакого не может быть такого т.к. out-of-order execution не может нарушить data-dependency.
Хотя тут видимо вообще в термин OOOE какой-то иной смысл вкладывается т.к. всегда это было такое архитектурное решение, которое позволяло выполнять несколько инструкций, если они не требовали одного и того же функционального юнита и не имели зависимостей по данным.Да может, может. Кто вам сказал, что переставление этих строк сломает программу в однопоточном режиме? Почему мы не можем попробовать предугадать булеан из calc(), и попробовать спекулятивно пойти дальше из какого-то конкретного предположения (напр, что он вернет true), а если мы ошебемся - откатить изменения? http://en.wikipedia.org/wiki/Branch_predictor

Я уже выражал эту мысль - нет смысла рассуждать о том, может он там что-то переставить или нет. Для нас это не имеет вообще никакого значения. Ну окей, не переставил он. Зато, например, переменная reslit расшарена между потоками, а потому для консистентного изменения нужно, скажем 20 тактов, а переменной reslitReady мы владеем эксклюзивно, и можем поменять ее в кэша за 1 такт. Вы итоге результат будет таким же, как если бы там был реордеринг - мы сначала увидим второе, а уже потом первое. С точки зрения программиста разницы никакой. Вы еще учтите, что каждый новый процессор, каждая новая версия JVMки могут иметь новые навороты. Сегодня у нас один механизм когерентности кэшей, завтра другой. Сегодня JIT переставляет инструкции с опаской, а завтра его заоптимизировали под конкретную платформу, и он начал их нещадно реордерить. Нам, джавистам, на это по-хе-рам . У нас есть JMM, которая снимает эту головную.
...
Рейтинг: 0 / 0
Reordering
    #38527558
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaВ ситуации отсутствия гонок весь этот сферический "реордеинг" в вакууме может быть исключительно результатом операций, которые допустимы конкретной для железки с поправкам на JMM*. А когда гонки есть, то JMM никаких детерминированных сценариев выполнения не гарантирует.И это так же неверный вывод. Там четко написано: не просто "will be sequentially consistent", " appear to be sequentially consistent". Не "является консистетным", а "выглядит консистетным", то есть дает предсказуемые результаты. А уж каким образом мы достигаем этих результатов - с реордерингами, или без оных, это уже дело третье.

Вы почитайте последние дискуссии в concurrency-interest. Там зубры вроде Дага и Шипилева как раз об этом писали, недавно. А именно: знаменитый JSR 133 Cookbook от Дага, где расписано, какие барьеры куда ставить, это консервативный подход . Но если, например, у вас будут какие-то глобальные эвристики, позволяющие точно знать, нужен ли в конкретном месте барьер или нет, то можно на лету решать ставить его, там или нет. Например, вот у нас запись в volatile, вроде как надо release семантику замутить. Но этот volatile нужен будет только одному другому треду, и то, когда у писателя точно переполнится store buffer, и он точно запишет это значение, а поток-читатель к тому вреени точно пройдется по своей текущей invalidate queue и точно увидит все актуальные значения. Ну и отлично, тогда мы вообще не будем туда никаких барьеров пихать, и без них сработает.
Это так, фантазия, которая возможно вообще никакого отношения к реальности не имеет, и не реализуема. Но тем не менее, она демонстрирует идею: не "является консистентным", а "выглядит консистентным", это разные вещи.
И опять таки - нам пофиг на это, у нас есть JMM.
...
Рейтинг: 0 / 0
Reordering
    #38527586
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvschwaТакого не может быть такого т.к. out-of-order execution не может нарушить data-dependency.
Хотя тут видимо вообще в термин OOOE какой-то иной смысл вкладывается т.к. всегда это было такое архитектурное решение, которое позволяло выполнять несколько инструкций, если они не требовали одного и того же функционального юнита и не имели зависимостей по данным.Да может, может. Кто вам сказал, что переставление этих строк сломает программу в однопоточном режиме? Почему мы не можем попробовать предугадать булеан из calc(), и попробовать спекулятивно пойти дальше из какого-то конкретного предположения (напр, что он вернет true), а если мы ошебемся - откатить изменения?
Только дело в том, что в коде выше ничего не надо предугадывать. Есть значение из какого-то расчета и потом это значение используется для следующего расчета.
...
Рейтинг: 0 / 0
Reordering
    #38527597
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaТолько дело в том, что в коде выше ничего не надо предугадывать. Есть значение из какого-то расчета и потом это значение используется для следующего расчета.Ну опять двадцать пять :-) Кто вам сказал, что не надо предугадывать? Вы это за процессор решили? В этом то и заключается speculative branch prediction, что мы можем вычислить reslitReady, не имея в руках reslit. Например, благодаря тому, что последние 1000 раз calc() возвращал true.

Но я еще раз повторю, даже жирным выделю: нет никакого смысла спорить о том, что именно там происходит в кишках. Это ничего не изменит, гарантий видимости как не было, так и нет.
...
Рейтинг: 0 / 0
Reordering
    #38527619
J.Serge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvВообще, мужики, потерпите, ждать осталось не долго - скоро будет готова моя первая часть тренинга по multithreading. В эту часть войдет вся теория по JMM, synchronized, volatile, final, а так же вопросы остановки потоков. Вчера как раз весь день рисовал схемки, как кэши работают :-)

А зачем рисовать схемки, если
cdtyjv.. нет никакого смысла спорить о том, что именно там происходит в кишках. Это ничего не изменит, гарантий видимости как не было, так и нет.

Держаться больше нету сил. Тренинг будет такой же сильный, как предыдущий?
...
Рейтинг: 0 / 0
Reordering
    #38527629
rfq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zu0FD,

Отлично! volatile спасет мир.
Мир, может, и спасет, а вас - нет.

Судя по всему, вы пытаетесь сделать передачу данных между потоками без использования стандартных механизмов типа BlockingThread и synchronized блоков. Это в принципе возможно, но сначала надо научится правильно пользоваться стандартными механизмами - synchronized, volatile, ReentrantLock, Atomic*, затем выучить JMM, затем то, что появится к этому времени в Java9...

А без этого бэкграунда у вас сегодня будет работать, а завтра - нет, и из проекта вы уже ушли, а пришедший вам на замену программист будет слать прокляться на вашу голову.
...
Рейтинг: 0 / 0
Reordering
    #38527630
rfq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zuесть такой код

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
    //first thread  
    reslit = calc();  
    reslitReady = true;
      
    //second thread  
    if (reslitReady){  
        takeDesision(reslit);  
    }  



А это происходит циклически или одноразово? Если циклически, то второй thread должен еще сбросить reslitReady, а первый ждать этого сброса прежде чем устанавливать reslitReady второй раз.

Почему бы вам просто не использовать очередь - даже если через нее будет передаваться единственное зyачение?
...
Рейтинг: 0 / 0
Reordering
    #38527633
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvschwaТолько дело в том, что в коде выше ничего не надо предугадывать. Есть значение из какого-то расчета и потом это значение используется для следующего расчета.Ну опять двадцать пять :-) Кто вам сказал, что не надо предугадывать? Вы это за процессор решили? В этом то и заключается speculative branch prediction, что мы можем вычислить reslitReady, не имея в руках reslit. Например, благодаря тому, что последние 1000 раз calc() возвращал true.

Но я еще раз повторю, даже жирным выделю: нет никакого смысла спорить о том, что именно там происходит в кишках. Это ничего не изменит, гарантий видимости как не было, так и нет.
При этом если знать, что код работает на каком-нибудь интелле с TLO + WC, то все будет гаратироваться хотя никаких гарантий от JMM у нас нет. Во как.
...
Рейтинг: 0 / 0
Reordering
    #38527634
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwacdtyjvпропущено...
Ну опять двадцать пять :-) Кто вам сказал, что не надо предугадывать? Вы это за процессор решили? В этом то и заключается speculative branch prediction, что мы можем вычислить reslitReady, не имея в руках reslit. Например, благодаря тому, что последние 1000 раз calc() возвращал true.

Но я еще раз повторю, даже жирным выделю: нет никакого смысла спорить о том, что именно там происходит в кишках. Это ничего не изменит, гарантий видимости как не было, так и нет.
При этом если знать, что код работает на каком-нибудь интелле с TLO + WCСС, то все будет гаратироваться хотя никаких гарантий от JMM у нас нет. Во как.
fixed.
...
Рейтинг: 0 / 0
Reordering
    #38527638
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaПри этом если знать, что код работает на каком-нибудь интелле с TLO + WC, то все будет гаратироваться хотя никаких гарантий от JMM у нас нет. Во как.Не знаю, что такое TLO, TSO может быть имелось ввиду? Как бы то ни было, вот код, который на моем Intel Core i5 никаких гарантий не дает, и при этом не работает:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
public class _02_visibility implements Runnable {
    /** Переменная, чье изменение ожидает увидеть другой поток. */
    private int val;
//    private volatile int val;

    /** {@inheritDoc} */
    @Override public void run() {
        // Инкремент переменной в цикле до тех пор, пока поток не заметит изменение переменной.
        int i = 0;

        while (val == 0)
            i++;

        System.out.println("Value change observed: " + i);
    }

    /**
     * Точка входа.
     */
    public static void main(String[] args) throws Exception {
        _02_visibility test = new _02_visibility();

        // Запуск потока.
        new Thread(test).start();

        // Даем время для старта второго потока.
        Thread.sleep(100);

        // После этого изменения второй поток должен остановиться.
        test.val = 1;

        System.out.println("Value changed.");
    }
}

Почему он не останавливается? А хз. Может из-за процессора, может из-за JITа, может еще из-за чего-то. В реальных задачах мне нафиг не упало возиться с PrintAssembly, и вдуплять, что именно там произошло. Код не работает. Важно не задрачиваться из-за конкретных причин, а знать, как устранить проблему.
...
Рейтинг: 0 / 0
Reordering
    #38527752
Alexey Tomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
J.SergeНа мой взгляд reordering чуть-чуть демонизируется.
Строки и инструкции java-кода одного Thread'а при исполнении никогда физически не меняются местами, а выполняются одна за другой.

Читайте доки.
У тебя есть две операции записи в память (два присвоения). Компилятор не переупорядочил, JIT не трогал, но процессор, уж так пришлось, запишет их из кэша в основную память другом порядке. Его право. И если еть другой поток, который исполняется на другом процессоре, то в каком порядке он увидит изменения переменных зафисит от такого количества параметров (включая состояние кэшей этого процессора), что об этом лучше не думать вообще, пока ты не понимаешь ВСЁ это.

Ещё раз- если не полного понимания микроархитектуры, процессоров, включая их взаимодействие в многопроцессорной системе - делайте строго по рекомендациям на основе JMM и не думайте более ни о чём.

Если вам приспичило заняться высокочастотным трейдингом или ещё чем- то вы должны знать точно процессор, на котором считаете, понимать всю работу кэшей и т.п. Тогда, если захотите, можете отступать от рекомендаций JMM.
...
Рейтинг: 0 / 0
Reordering
    #38527758
J.Serge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey Tomin,

спасибо за прочтение и понимание того, что я написал выше
...
Рейтинг: 0 / 0
Reordering
    #38527842
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvПочему он не останавливается? А хз. Может из-за процессора, может из-за JITа, может еще из-за чего-то. В реальных задачах мне нафиг не упало возиться с PrintAssembly, и вдуплять, что именно там произошло. Код не работает. Важно не задрачиваться из-за конкретных причин, а знать, как устранить проблему.

Да знаете, пробовали ведь
// private volatile int val;
если убрать комментарий, работает ведь.
cdtyjv, 15409479 тут масштабы что делает программа и процессор несколько несопоставимы, и это мягко сказано.
...
Рейтинг: 0 / 0
Reordering
    #38527913
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, можете помучить вот этот код:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
import sun.misc.*;

import java.lang.reflect.*;
import java.security.*;

public class Test {
    /**
     * Main method.
     *
     * @param args Arguments, none required.
     * @throws Exception Failure.
     */
    public static void main(String[] args) throws Exception {
        final ValueHolder holder = new PlainValueHolder();

        new Thread(new Runnable() {
            @Override 
            public void run() {
                int i = 0;

                while (holder.get() == 0)
                    i++;

                System.out.println("Value change observed: " + holder.get());
            }
        }).start();

        Thread.sleep(100);

        holder.set(1);

        System.out.println("Value changed.");
    }

    /**
     * Value holder.
     */
    private static interface ValueHolder {
        /**
         * Get value.
         *
         * @return Value.
         */
        public int get();

        /**
         * Set value.
         *
         * @param val Value.
         */
        public void set(int val);
    }

    /**
     * Value holder with regular field access.
     */
    private static class PlainValueHolder implements ValueHolder {
        /** Value. */
        private int val;

        /** {@inheritDoc} */
        @Override 
        public int get() {
            return val;
        }

        /** {@inheritDoc} */
        @Override 
        public void set(int val) {
            this.val = val;
        }
    }

    /**
     * Value holder with volatile field access.
     */
    private static class VolatileValueHolder implements ValueHolder {
        /** Value. */
        private volatile int val;

        /** {@inheritDoc} */
        @Override 
        public int get() {
            return val;
        }

        /** {@inheritDoc} */
        @Override 
        public void set(int val) {
            this.val = val;
        }
    }

    /**
     * Value holder with regular field access through unsafe.
     */
    private static class PlainUnsafeValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override 
        public int get() {
            return unsafe().getInt(this, offset);
        }

        /** {@inheritDoc} */
        @Override 
        public void set(int val) {
            unsafe().putInt(this, offset, val);
        }
    }

    /**
     * Value holder with volatile field read through unsafe and regular field write.
     */
    private static class ReadVolatileValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override 
        public int get() {
            return unsafe().getIntVolatile(this, offset);
        }

        /** {@inheritDoc} */
        @Override 
        public void set(int val) {
            this.val = val;
        }
    }

    /**
     * Value holder with regular field read and volatile field write through unsafe.
     */
    private static class WriteVolatileValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override 
        public int get() {
            return val;
        }

        /** {@inheritDoc} */
        @Override 
        public void set(int val) {
            unsafe().putIntVolatile(this, offset, val);
        }
    }

    /**
     * Value holder with regular field read and ordered field write through unsafe.
     */
    private static class WriteOrderedValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override 
        public int get() {
            return val;
        }

        /** {@inheritDoc} */
        @Override 
        public void set(int val) {
            unsafe().putOrderedInt(this, offset, val);
        }
    }

    /**
     * Value holder with regular field read guarded with monitor enter and regular field write.
     */
    private static class MonitorEnterValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override 
        public int get() {
            unsafe().monitorEnter(this);

            return val;
        }

        /** {@inheritDoc} */
        @Override 
        public void set(int val) {
            this.val = val;
        }
    }

    /**
     * Base class for value holders using unsafe.
     */
    private abstract static class UnsafeValueHolder implements ValueHolder {
        /** Unsafe. */
        protected final Unsafe unsafe;

        /** Field offset. */
        protected final long offset;

        /** Value. */
        protected int val;

        /**
         * Constructor.
         */
        protected UnsafeValueHolder() {
            try {
                unsafe = unsafe();

                offset = unsafe.objectFieldOffset(UnsafeValueHolder.class.getDeclaredField("val"));
            }
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * Get instance of Unsafe.
         *
         * @return Instance of Unsafe.
         */
        protected Unsafe unsafe() {
            try {
                return Unsafe.getUnsafe();
            }
            catch (SecurityException ignored) {
                try {
                    return AccessController.doPrivileged
                        (new PrivilegedExceptionAction<Unsafe>() {
                            @Override
                            public Unsafe run() throws Exception {
                                Field f = Unsafe.class.getDeclaredField("theUnsafe");

                                f.setAccessible(true);

                                return (Unsafe) f.get(null);
                            }
                        });
                }
                catch (PrivilegedActionException e) {
                    throw new RuntimeException("Failed to get Unsafe.", e.getCause());
                }
            }
        }
    }
}

На моих интелах результаты такие:

PlainValueHolder - не работает;
VolatileValueHolder - работает;
PlainUnsafeValueHolder - работает;
ReadVolatileValueHolder - работает;
WriteVolatileValueHolder - не работает;
WriteOrderedValueHolder- не работает;

MonitorEnterValueHolder - работает.

Какие можно из этого сделать выводы? Обычный доступ не работает, это понятно. Чтения через acquire работают (VolatileValueHolder, ReadVolatileValueHolder, MonitorEnterValueHolder), это тоже понятно. Но вот какого хрена работает PlainUnsafeValueHolder без всяких барьеров? И почему не работает WriteVolatileValueHolder с записью с release?
Да очень просто - значит это не железяка выкобенивается, а компилятор. Когда я делаю обычное чтение через Unsafe, явно задав адрес, откуда читать - он видит апдейт. А обычные чтения апдейт не видят, так как компилятор то ли сделал себе локальную копию, то ли еще что-то. А acquire семантика убивает эту оптимизацию, тем самым позволяя нам таки увидеть изменившееся значение.

Это еще раз к тезису о том, что не так важно, понимать, почему именно программа ведет себя некорректно. Важно понимать принципы решения этих проблем.
...
Рейтинг: 0 / 0
Reordering
    #38527948
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvschwaПри этом если знать, что код работает на каком-нибудь интелле с TLO + WC, то все будет гаратироваться хотя никаких гарантий от JMM у нас нет. Во как.Не знаю, что такое TLO, TSO может быть имелось ввиду? Как бы то ни было, вот код, который на моем Intel Core i5 никаких гарантий не дает, и при этом не работает:
Конечно такой код не работает. И если это был самый последний код, которые выполняется при завершении программы, то она бы не остановилась. А вот если он был бы расположен где-то в глубине, когда дальше будут идти запаси и обращения к "общим" локациям памяти, то все бы сработало как надо. Только это факт того, что в конкретном случае это работать будет, а не рекомендация к тому, что так делать нужно.

p.s.
TLO = Total Lock Order
...
Рейтинг: 0 / 0
Reordering
    #38527974
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaИ если это был самый последний код, которые выполняется при завершении программы, то она бы не остановилась. А вот если он был бы расположен где-то в глубине, когда дальше будут идти запаси и обращения к "общим" локациям памяти, то все бы сработало как надо.Вы почитайте мой пост выше с анализом причин этого, и поймете, что данный код ломается независимо от "глубины".

schwaTLO = Total Lock OrderГугл такого не знает.
...
Рейтинг: 0 / 0
Reordering
    #38528036
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот апдейт тестового кода, который демонстрирует, что никакая "глубина" нас не спасает:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
import sun.misc.*;

import java.lang.reflect.*;
import java.security.*;
import java.util.concurrent.*;

public class Test {
    /** Expected cache size. */
    private static final int CACHE_SIZE = 10 * 1024 * 1024;

    /** Expected cache line size. */
    private static final int CACHE_LINE_SIZE = 64;

    /** Amount of secondary threads. */
    private static final int THREAD_COUNT = Runtime.getRuntime().availableProcessors() * 2;

    /** Monitor. */
    private static final Object mux = new Object();

    /**
     * Main method.
     *
     * @param args Arguments, none required.
     * @throws Exception Failure.
     */
    public static void main(String[] args) throws Exception {
        final ValueHolder holder = new PlainValueHolder();

        final CacheLine[] cache = new CacheLine[CACHE_SIZE / CACHE_LINE_SIZE];

        for (int i = 0; i < CACHE_SIZE / CACHE_LINE_SIZE; i++)
            cache[i] = new CacheLine();

        new Thread(new Runnable() {
            @Override
            public void run() {
                int i = 0;

                while (holder.get() == 0)
                    i++;

                System.out.println("Value change observed: " + i);
            }
        }).start();

        Thread.sleep(100);

        final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT);

        Thread[] threads = new Thread[THREAD_COUNT];

        for (int i = 0; i < THREAD_COUNT; i++) {
            final int idx = i + 1;

            Thread thread = new Thread(new Runnable() {
                @Override 
                public void run() {
                    synchronized (mux) {
                        holder.set(idx);
                    }

                    System.out.println("Value changed from another thread: " + idx);

                    try {
                        barrier.await();
                    }
                    catch (Exception ignore) {

                    }

                    for (CacheLine cacheLine : cache)
                        cacheLine.change();
                }
            });

            thread.start();

            threads[i] = thread;
        }

        for (Thread thread : threads)
            thread.join();

        // Iterate over all cache lines to prevent optimizations.
        long sum = 0;

        for (CacheLine line : cache)
            sum += line.sum();

        System.out.println("Iterated over cache content: " + sum);
    }

    /**
     * Cache line abstraction.
     */
    private static class CacheLine {
        /** Array. */
        private final long[] arr = new long[CACHE_LINE_SIZE / 8];

        /** Next index to change. */
        private int nextIdx;

        /**
         * Change some value in cache line.
         */
        public void change() {
            synchronized (mux) {
                for (int i = 0; i < 100 * arr.length; i++)
                    arr[nextIdx++ % arr.length]++;
            }
        }

        /**
         * Calculate cache line sum.
         *
         * @return Cache line sum.
         */
        public long sum() {
            long sum = 0;

            for (long item : arr)
                sum += item;

            return sum;
        }
    }

    /**
     * Value holder.
     */
    private static interface ValueHolder {
        /**
         * Get value.
         *
         * @return Value.
         */
        public int get();

        /**
         * Set value.
         *
         * @param val Value.
         */
        public void set(int val);
    }

    /**
     * Value holder with regular field access.
     */
    private static class PlainValueHolder implements ValueHolder {
        /** Value. */
        private int val;

        /** {@inheritDoc} */
        @Override
        public int get() {
            return val;
        }

        /** {@inheritDoc} */
        @Override
        public void set(int val) {
            this.val = val;
        }
    }

    /**
     * Value holder with volatile field access.
     */
    private static class VolatileValueHolder implements ValueHolder {
        /** Value. */
        private volatile int val;

        /** {@inheritDoc} */
        @Override
        public int get() {
            return val;
        }

        /** {@inheritDoc} */
        @Override
        public void set(int val) {
            this.val = val;
        }
    }

    /**
     * Value holder with regular field access through unsafe.
     */
    private static class PlainUnsafeValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override
        public int get() {
            return unsafe.getInt(this, offset);
        }

        /** {@inheritDoc} */
        @Override
        public void set(int val) {
            unsafe.putInt(this, offset, val);
        }
    }

    /**
     * Value holder with volatile field read through unsafe and regular field write.
     */
    private static class ReadVolatileValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override
        public int get() {
            return unsafe.getIntVolatile(this, offset);
        }

        /** {@inheritDoc} */
        @Override
        public void set(int val) {
            this.val = val;
        }
    }

    /**
     * Value holder with regular field read and volatile field write through unsafe.
     */
    private static class WriteVolatileValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override
        public int get() {
            return val;
        }

        /** {@inheritDoc} */
        @Override
        public void set(int val) {
            unsafe.putIntVolatile(this, offset, val);
        }
    }

    /**
     * Value holder with regular field read and ordered field write through unsafe.
     */
    private static class WriteOrderedValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override
        public int get() {
            return val;
        }

        /** {@inheritDoc} */
        @Override
        public void set(int val) {
            unsafe.putOrderedInt(this, offset, val);
        }
    }

    /**
     * Value holder with regular field read guarded with monitor enter and regular field write.
     */
    private static class MonitorEnterValueHolder extends UnsafeValueHolder {
        /** {@inheritDoc} */
        @Override
        public int get() {
            unsafe.monitorEnter(this);

            return val;
        }

        /** {@inheritDoc} */
        @Override
        public void set(int val) {
            this.val = val;
        }
    }

    /**
     * Base class for value holders using unsafe.
     */
    private abstract static class UnsafeValueHolder implements ValueHolder {
        /** Unsafe. */
        protected final Unsafe unsafe;

        /** Field offset. */
        protected final long offset;

        /** Value. */
        protected int val;

        /**
         * Constructor.
         */
        protected UnsafeValueHolder() {
            try {
                unsafe = unsafe();

                offset = unsafe.objectFieldOffset(UnsafeValueHolder.class.getDeclaredField("val"));
            }
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * Get instance of Unsafe.
         *
         * @return Instance of Unsafe.
         */
        private Unsafe unsafe() {
            try {
                return Unsafe.getUnsafe();
            }
            catch (SecurityException ignored) {
                try {
                    return AccessController.doPrivileged
                        (new PrivilegedExceptionAction<Unsafe>() {
                            @Override
                            public Unsafe run() throws Exception {
                                Field f = Unsafe.class.getDeclaredField("theUnsafe");

                                f.setAccessible(true);

                                return (Unsafe) f.get(null);
                            }
                        });
                }
                catch (PrivilegedActionException e) {
                    throw new RuntimeException("Failed to get Unsafe.", e.getCause());
                }
            }
        }
    }
}

И synchronized c контешном у нас там есть, и кэш мы весь гарантированно перелопатили на всех корах ... и все равно ничего не помогает.
...
Рейтинг: 0 / 0
Reordering
    #38528070
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,

Это называется давай обманем jit, пусть думает что это обычная, а мы будет использовать семантику volatile и посмотрим что будет. Вот что Вы ожидаете когда определяете
protected int val;
а используете unsafe.getIntVolatile(this, offset);
...
Рейтинг: 0 / 0
Reordering
    #38528098
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
0FD ,
Я ничего не ожидаю, я лишь демонстрирую, как разные способы чтения влияют на то, завершится программа или нет.
...
Рейтинг: 0 / 0
Reordering
    #38528579
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvschwaИ если это был самый последний код, которые выполняется при завершении программы, то она бы не остановилась. А вот если он был бы расположен где-то в глубине, когда дальше будут идти запаси и обращения к "общим" локациям памяти, то все бы сработало как надо.Вы почитайте мой пост выше с анализом причин этого, и поймете, что данный код ломается независимо от "глубины".
Только вот с тем, что это код будет ломаться никто и не спорил ;)
cdtyjvГугл такого не знает.
Невезение с гуглом. Мне он выдает цитаты из соответствующих мануалов в первых же результатах поиска.
...
Рейтинг: 0 / 0
Reordering
    #38528599
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaТолько вот с тем, что это код будет ломаться никто и не спорил ;)Ну вы же сказали, что при обращении к "общим" локациям памяти все будет нормально. Как видно из кода, не будет.

schwaНевезение с гуглом. Мне он выдает цитаты из соответствующих мануалов в первых же результатах поиска.Поделитесь ссылочкой.
...
Рейтинг: 0 / 0
Reordering
    #38528789
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123ну дак, они взаимодействуют по контрактуЭтот контракт реализует вполне конкретный человек.
Который может понавтыкать в своём коде всяческих чудес, которые прекрасно пройдут все юнит-тесты и начнут глючить, когда встанут под промышленную нагрузку. Не всегда, а так ... Время от времени, но всегда не ко времени.
...
Рейтинг: 0 / 0
Reordering
    #38529030
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovPetro123ну дак, они взаимодействуют по контрактуЭтот контракт реализует вполне конкретный человек.
Который может понавтыкать в своём коде всяческих чудес, которые прекрасно пройдут все юнит-тесты и начнут глючить, когда встанут под промышленную нагрузку. Не всегда, а так ... Время от времени, но всегда не ко времени.
Тут 2 момента:
- библиотеки...IDE...ЯП должен помогать программисту не писать Г.
Так, например, в Delphi для потока, нужно отнаследоваться от класса Поток.
- сам программист конечно тоже выполняет контракт. И не запускает поток, пока все данные для него не готовы.
А если уж припёрло на всём ходу использовать глобальную переменную, то ставь критическую секцию
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Section:=TCriticalSection.Create;

procedure IncElem;
var i: byte;
begin
  Section.Enter;
  for i:=1 to 100 do
     Inc(mas[i]);
  Section.Leave;
end;


...
А в одном потоке все инструкции должны идти ожидаемо, и так как написано).
IMHO
...
Рейтинг: 0 / 0
Reordering
    #38529106
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123Тут 2 момента:
- библиотеки...IDE...ЯП должен помогать программисту не писать Г."Охренеть! Дайте две!"
Так, например, в Delphi для потока, нужно отнаследоваться от класса ПотокВ Java, что характерно - тоже. Ну или интерфейс реализовать соответствующий.сам программист конечно тоже выполняет контрактЕсть такой термин - "функциональная неграмотность". Это когда человек может читать, но не может понимать прочитанное.
Толку с вашего "тоже выполняет", если конкретный программист ни уха ни рыла в конкурентном программировании?
Он или засинхронизируется насмерть и будет работать в один поток или сделает глюкающий код.
...
Рейтинг: 0 / 0
Reordering
    #38529275
rfq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zig zucdtyjv,

а вот в тот момент, когда процессор начал заниматься предсказаниями и выполнил одно из них "присваивает reslitReady = true", это вот предсказанное значение уже может увидеть второй поток?
Нет, не может. Все сделано так, что для программиста нет разницы, делал процессор спекулятивное выполнение или нет - разве что общее время получается разным.
...
Рейтинг: 0 / 0
Reordering
    #38529312
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,
1. Именно библиотеки или компилятор)).
Например, для установки глобального хука в Вин32 (перехват клавиатуры), передавая функцию класса - у вас код просто не скомпилится. Можно передать только неклассовую (в Delphi).
Ну и т.д....много есть примеров помощи))
2. Если он неграмотен - нефиг потоки писать. Они нужны не так много мест.
Загрузил хотя бы одним потоком все ядра)).
Пусть пишет прикладной код...или сервлеты. Там потоки снаружи и не видны...контейнер помогает.
Удачи!
...
Рейтинг: 0 / 0
Reordering
    #38529317
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rfqВсе сделано так, что для программиста нет разницы, делал процессор спекулятивное выполнение или нет
я тоже за это imho)
...
Рейтинг: 0 / 0
Reordering
    #38529322
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123Загрузил хотя бы одним потоком все ядра)).

:)
...
Рейтинг: 0 / 0
Reordering
    #38529359
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rfqНет, не может. Все сделано так, что для программиста нет разницы, делал процессор спекулятивное выполнение или нет - разве что общее время получается разным.Ну вот кто вам такое сказал? Даже если процессор спекулятивно пошел по ошибочному бранчу, и начал что-то писать, это вовсе не значит, что sequential consistency сломается в потоке, в котором эта спекуляция произошла. Тем не менее, большинство (если не все) распространенных процессоров так не делают. Не потому, что это невозможно в принципе, а потому что просто инженеры решили пойти другим путем. Вот, что написано в одной из диссертаций ( http://www3.ece.neu.edu/~yilmazer/thesis/thesis.pdf) на эту тему:
AYSE YILMAZERTo maintain the illusion of sequential consistency, a store instruction cannot write its value to memory until it becomes the oldest (i.e., non-speculative) instruction in the processor.То есть да, пока мы не узнаем гарантированно, что данный бранч не является спекулятивным, мы не будем писать это в память. А следовательно, другие потоки не увидят спекуляцию. НО! Далее идет следующее замечание:
AYSE YILMAZERIn this study, we did not consider the multiprocessors based on uniprocessors that may speculatively execute store instructions, such as the speculative versioning cache of Multiscalar [22], or Levo [24].О как оно оказывается. Есть процессоры, которые могут спекулятивно писать в память. И если вы сейчас сидите на каком-нибудь Интеле, который это не делает, это не означает, что следующее поколение их же процессоров этого делать не будет.

В десятый раз поторюсь: рассуждать на тему того, что именно может делать какой-то абстрактный процессор в вакууме, это все от лукавого.
...
Рейтинг: 0 / 0
Reordering
    #38529528
rfq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv И если вы сейчас сидите на каком-нибудь Интеле, который это не делает, это не означает, что следующее поколение их же процессоров этого делать не будет.


Интересно, не знал о Мultiscalar и Levo.
Тем не менее, речь-то идет о Java, и даже если она будет портирована на подобные экзотические процессоры, я думаю, что спекулятивная запись в память будет зарублена. Во всяком случае, я сомневаюсь, что такая запись в память допускается спецификацией JVM.
...
Рейтинг: 0 / 0
Reordering
    #38529619
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Reordering
    #38529671
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvAYSE YILMAZERIn this study, we did not consider the multiprocessors based on uniprocessors that may speculatively execute store instructions, such as the speculative versioning cache of Multiscalar [22], or Levo [24].О как оно оказывается. Есть процессоры, которые могут спекулятивно писать в память. И если вы сейчас сидите на каком-нибудь Интеле, который это не делает, это не означает, что следующее поколение их же процессоров этого делать не будет.
А точно программа это поведение сможет обозреть, если вместе с введением этих оптимизаций идут правки в протоколы конгерентности кэшей и др. ? Просто в противном случае подобная оптимизация может сломать даже корректную программу.
...
Рейтинг: 0 / 0
Reordering
    #38529692
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rfqТем не менее, речь-то идет о Java, и даже если она будет портирована на подобные экзотические процессоры, я думаю, что спекулятивная запись в память будет зарублена. Во всяком случае, я сомневаюсь, что такая запись в память допускается спецификацией JVM.Спецификация JVM не оперирует такими понятиями, как "спекулятивная запись" в принципе. JVM для корректной работы нужно две вещи:
1) Sequential consistency по умолчанию для одного потока - что бы работали однопоточные программы;
2) Sequential consistency _по_требованию_ для нескольких потоков - что бы работали многопоточные программы.

Что здесь интересно? Если будет отсутствовать п.1, то у вас не будет работать не только JVM, но и все остальные современные приложения. Ибо без sequential consistency запрограммировать что-либо можно только в теории, но не практике.

А если будет отсутствовать п.2, то у вас не будет работать не только JVM с несколькими потоками, но и все остальные современные приложения. Ибо что из себя представляют понятия, из того же JSR133 Cookbook? Всякие там StoreLoad и иже с ними? Это просто логичесике обертки над какими-то физическими инструкциями процессора и правилами компилятора. Не более того. Если для этих логических оберток нет конкретных решений на конкретной платформе, значит она не предназначена для многопоточной работы в принципе.
...
Рейтинг: 0 / 0
Reordering
    #38529707
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaА точно программа это поведение сможет обозреть, если вместе с введением этих оптимизаций идут правки в протоколы конгерентности кэшей и др. ? Просто в противном случае подобная оптимизация может сломать даже корректную программу.Вопрос лишен смысла. Я могу с таким же успехом спросить: "А точно ли текущая модель работы с памятью x86 работает правильно?" Теоретически, она может работать правильно. Работает ли она правильно по факту - не знаю.
Так же и со спекулятивными записями. Может ли такой подход работать теоретически? Да, может. Работает ли он корректно в конкретном экземпляре Multiscaler/Levo? Не знаю.
...
Рейтинг: 0 / 0
Reordering
    #38529924
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvschwaА точно программа это поведение сможет обозреть, если вместе с введением этих оптимизаций идут правки в протоколы конгерентности кэшей и др. ? Просто в противном случае подобная оптимизация может сломать даже корректную программу.Вопрос лишен смысла. Я могу с таким же успехом спросить: "А точно ли текущая модель работы с памятью x86 работает правильно?" Теоретически, она может работать правильно. Работает ли она правильно по факту - не знаю.
Так же и со спекулятивными записями. Может ли такой подход работать теоретически? Да, может. Работает ли он корректно в конкретном экземпляре Multiscaler/Levo? Не знаю.
Этот вопрос лишен смысла только для тех, кто не видит разницы между вычитываем старого значения и выполнением участков кода, которые выполнится никак не могли вообще ибо они используют значение, которые никакими операциями, которые выполнялись в программе получено не было.
...
Рейтинг: 0 / 0
Reordering
    #38529932
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О чем спор, а то я запутался?
...
Рейтинг: 0 / 0
Reordering
    #38529939
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никО чем спор, а то я запутался?
О том что реордеринг можно наблюдать далеко не на всех архитектурах.
...
Рейтинг: 0 / 0
Reordering
    #38529962
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaЭтот вопрос лишен смысла только для тех, кто не видит разницы между вычитываем старого значения и выполнением участков кода, которые выполнится никак не могли вообще ибо они используют значение, которые никакими операциями, которые выполнялись в программе получено не было.Ничего не понял, сформулируйте свой вопрос еще раз.
Вот мы спекулятивно предположили, что значение calc() вернет true, и пошли в соответствующий бранч. В этом бранче вы выполняем какие-то операции. Потом мы узнали, что calc() на самом деле вернул false. Окей, мы берем и откатываем те изменения, которые успели нагородить, и заново выполняем код с того момента, когда мы сделали ошибочное предположение.
Это не какие-то мои додумки, так работают все современные процессоры, почитайте любой мануал, ключевое слово - "speculative branch prediction".

НО! Современные процессоры не допускают спекулятивные записи в кэш. Они спекулятивно меняют значения только в рамках регистров процессора. А те архитектуры, что я указал выше, могут записать спекулятивное значение и в свой кэш, и даже в кэш другого ядра. И это будет работать до тех пора, пока данные изменения можно откатить. А откатить их можно.

И с точки зрения sequential consistency в рамках одного потока, абсолютно пофиг, где сейчас находятся спекулятивные (то есть потенциально некорректные) значения - в регистрах, в кэшах, или где-либо еще. Потому я и не могу понять, что вы хотите донести.

P.S.: Я надеюсь, что все понимают, что когда я говорю "начал спекулятивно выполнять бранч" != "начал спекулятивно выполнять все инструкции в этом бранче". Спекулятивно можно выполнять только то, что можно откатить. Поэтому, например, никто не будет спекулятивно джампить System.out.println(), так как в случае ошибки мы это не сможем откатить. Спекулятивно выполняются только те инструкции, ущерб от которых конкретный процессор сможет компенсировать.
...
Рейтинг: 0 / 0
Reordering
    #38529976
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvСпекулятивно можно выполнять только то, что можно откатить.
Да там наверное десяток машинных инструкций можно откатить, а Вы размахнулись.
...
Рейтинг: 0 / 0
Reordering
    #38530064
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,

Результата работы этих спекулятивных лоудов и сторов никакая программа обозреть не сможет. И как в случае с обычным спекулятивным выполнением также никому ничего не будет видно*.

* - Разве что кто-то может обозреть увеличение сумм в счетах за электричество, но эти люди уже не разработчики программ.
...
Рейтинг: 0 / 0
Reordering
    #38530111
rfq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvВ десятый раз поторюсь: рассуждать на тему того, что именно может делать какой-то абстрактный процессор в вакууме, это все от лукавого.
Мы здесь рассуждаем не об абстрактном процессоре в вакууме, а о JVM. Любая реализация JVM на каком угодно процессоре должна вести себя одинаково. Раз интерпретатор, сделанный по букве спецификации, никогда не записывает мусорные значения в память, которые могут быть замечены другим потоком, то и все остальные реализации не должны этого делать.
...
Рейтинг: 0 / 0
Reordering
    #38530147
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rfqЛюбая реализация JVM на каком угодно процессоре должна вести себя одинаково.Кто вам это сказал? Где это написано в спецификации? Они должны вести себя одинаково в рамках JMM. А JMM ничего не говорит ни о реордерингах, ни о кэшах, ни о чем-либо подобном. Она лишь дает набор правил, которым должна следовать JVM. И одно из этих правил, например, гласит: volailte чтение, следующее после volatile записи, гарантированно увидит результат этой записи. То есть, вам дают гарантию, что вы увидите что-то определенное, после того, как предпримете определенные шаги (в данном случае - обеспечите волатильное чтение, которое гарантированно идет после волатильной записи).


rfqРаз интерпретатор, сделанный по букве спецификации, никогда не записывает мусорные значения в память, которые могут быть замечены другим потоком, то и все остальные реализации не должны этого делать.Это что еще за глупость? Покажите мне, где в спецификации написано, что "интерпретатор не записывает мусорные значения в память". Можете сслыку на это привести? Думаю нет, так как это плод вашей фантазии, который к реальности отношения не имеет.
JMM говорит нам: если один поток записал что-то в переменную, то мы не можем ничего сказать, что увидит другой поток. В спецификации не сказано "вы увидите актуальное значение". В ней не сказано "вы увидите старое значение". В ней сказано: " мы не знаем, что вы там увидите ". Может быть старое значение, может быть новое значение, может быть это будет мусорный результат спекуляции, может это будет мусорный результат неатомарной записи long/double значения, да что угодно это может быть. Мы не даем никаких гарантий. Хотите быть в чем-то уверенными? Тогда вот вам synchronized-with, вот вам исключение в лице final - в этих случаях у вас будут гарантии, что вы увидите ровно то, что должны увидеть.

Еще раз, что бы уж точно усвоилось: выбор идет не между "старым" и "актуальным", а между "актуальным" и "не актуальным". А что такое "не актуальное" спецификация не говорит .
...
Рейтинг: 0 / 0
Reordering
    #38530152
rfq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvВ ней сказано: " мы не знаем, что вы там увидите ". Может быть старое значение, может быть новое значение, может быть это будет мусорный результат спекуляции, может это будет мусорный результат неатомарной записи long/double значения, да что угодно это может быть.
В каком месте это сказано?
...
Рейтинг: 0 / 0
Reordering
    #38530190
Alexey Tomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rfqcdtyjvВ ней сказано: " мы не знаем, что вы там увидите ". Может быть старое значение, может быть новое значение, может быть это будет мусорный результат спекуляции, может это будет мусорный результат неатомарной записи long/double значения, да что угодно это может быть.
В каком месте это сказано?

Там не сказано иное. А гарантируется только то, что указано явно. Реализаторы JVM должны обеспечить выполнение некоторых правил. Остальное- как повезёт.

"Переупорядочивание", ещё раз, в основном итог взаимодействия ПРОЦЕССОРОВ. JVM обязана бороться с ним в указанных рамках. В остальных- как 247й транзистор контроллера памяти захотел- так и переупорядочится запись С ТОЧКИ ЗРЕНИЯ соседнего процесса.

Одномоментность при взгляде с разных мест разная :)

PS: где вы вообще видели интерпретатор JVM? Давно уже компилятор в большинстве случаев работает.
...
Рейтинг: 0 / 0
Reordering
    #38530210
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rfqcdtyjvВ ней сказано: " мы не знаем, что вы там увидите ". Может быть старое значение, может быть новое значение, может быть это будет мусорный результат спекуляции, может это будет мусорный результат неатомарной записи long/double значения, да что угодно это может быть.
В каком месте это сказано?Более глубокое изучение JMM показало следующее:
1) JMM запрещает out-og-thin-air значения даже для некорректно синхронизированных программ. Формально это означает, что если я читаю X, то прочитанное мной значение обязательно должно было быть _честно_ записано туда ранее. Так как спекулятивные записи к _честным_ не относятся, то чтение спекулятивных значений в JMM запрещено. Формально это описано вот в этой главе JLS - http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.8 . А более человеческим языком вот здесь - http://cseweb.ucsd.edu/classes/fa05/cse231/Fish.pdf .
2) При всем при этом, как мы знаем, JMM допускает неатомарные записи long/double. То есть, если у меня был long, иниициализированный нулем, один тред записал туда 0xffffffff00000000, а другой 0x00000000ffffffff, то третий поток может увидеть не три, а четыре значения: 0, 0x00000000ffffffff, 0xffffffff00000000 и 0xffffffffffffffff .

Лично я не вижу отличий между тем, что поток увидит какое-то левое значение, из-за того, что две одновременные записи long "наложились" друг на друга, и тем, что поток увидит спекулятивную запись, которая потом будет откачена. А JMM эти два случая разделяет. То есть, неатомарная запись long/double, это по логике вещей вроде бы out-of-thin-air, а вроде бы и нет.
Собственно, поэтому я и настаивал на том, что чтение спекулятивной записи не запрещено, ибо я не вижу разницы между этими двумя случаями.

Как это понять - хз. Думаю, здесь спасет разве что письмо в concurrency-interest в надежде услышать ответ от отцов-основателей JMM. Что я сегодня и сделаю, а потом напишу ответ на Хабре, ибо жесть.
...
Рейтинг: 0 / 0
Reordering
    #38530243
J.Serge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл никО чем спор, а то я запутался?

Отличный вопрос.
Я бы сказал так: с автором тренингов спорят о том, стоит ли вводить излишние сущности там, где они не нужны.
Спор примерно такой:
ТС2 * 2 = 4 - это верно только в однопоточной программе, а в многопоточный программе иначе?
звезда тренинговКто вам такое сказал? В десятичной системе счисления - да, но вот в троичной совсем иначе! Так что, если вы хотите правильно считать в десятичной системе, учите правила! И потерпите, я скоро буду у вас в городе с циклом лекций по таблице умножения
ТСУ меня вроде десятичная...
звезда тренинговНу и что? Есть еще, например, двоичная...
всеНо у нас же десятичная!!
звезда тренинговЭто да, но вот есть еще комплексные числа...
всеНо у нас же десятичная!!!
звезда тренинговТак-то оно так, но вот в другой галактике...

Примерно в таком ключе
...
Рейтинг: 0 / 0
Reordering
    #38530274
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
После тяжелых дум я таки разобрался в вопросе. Итого:
1) Принципиальное отличие между word tearing (т.е. когда мы засрали long/double конкурирующими неатомарными записями) принципиально отличается от гипотетической ошибочной спекулятивной записи тем, что результат word tearing может оставаться актуальным неограниченно долго, а спекулятивная ошибка eventually будет откачена. Таким образом, результат word tearing можно рассматривать, как результат нормального store commit, и его нельзя отнести к out-of-thin-air в том значение, которое использует JMM.
2) Тем не менее, наличие out-of-thin-air результатов не является препятствием для создания рабочих моделей памяти. Пример - модель памяти C++11. Изначально она допускала такое. В 2012 пошли разговоры о том, что бы пойти путем Java, и запретить это ( http://preshing.com/20120625/memory-ordering-at-compile-time/ ). Чем в итоге кончилось - не знаю.
3) Мотивация создателей JMM по запрету out-of-thin-air значений была по сути одна - безопасность. Так как Java ставит security во главу угла (а мы на нее постоянно благополучно кладем. отключая SecurityManager ), ситуация, когда мы можем увидеть какое-то непонятное значение недопустима, так как этим "смотрящим" может быть не-trusted код, а "непонятным значением" может оказаться какой-нибудь пароль. А мы хотим, что бы даже те программисты, которые незнакомы с JMM, могли писать по возможности максимально безопасный код.
...
Рейтинг: 0 / 0
Reordering
    #38530482
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Результаты спекулятивного выполнения смогли продержаться невидимыми для программы на протяжении одного сообщения, но потом снова стали видны благодаря какой-то мистической силе JMM. Это уже победа.
...
Рейтинг: 0 / 0
Reordering
    #38574982
Alexey Tomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Недавно наткнулся на
YouTube Video
...
Рейтинг: 0 / 0
Reordering
    #38575032
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey TominНедавно наткнулся на
Ну, Шипилев же. Уже легендарный докладчик. Если понравилось, ищи все его даклады. И на хабре статьи у него клевые.
...
Рейтинг: 0 / 0
Reordering
    #38575180
Alexey Tomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczAlexey TominНедавно наткнулся на
Ну, Шипилев же. Уже легендарный докладчик. Если понравилось, ищи все его даклады. И на хабре статьи у него клевые.

Да я знаю- слушал и вживую много раз. Но обычно всё были заковыристые темы, типа "как я провёл лето" "как я сломал JVM нафиг"- а тут именно ликбез "от и до".
...
Рейтинг: 0 / 0
83 сообщений из 83, показаны все 4 страниц
Форумы / Java [игнор отключен] [закрыт для гостей] / Reordering
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]