Re: Запись в массив double-ов из нескольких потоков
От: Pavel Dvorkin Россия  
Дата: 11.05.11 07:13
Оценка: 5 (1) +1 -1 :)
Здравствуйте, kuaw26, Вы писали:

K>Есть массив double-ов. Есть несколько потоков которые считают функцию качества и результат кладут в этот массив.

K>Каждый поток работает со своей частью массива и по индексам не пересекаются.
K>Можно ли работать с массивом без синхронизации?

K>у меня пока не вышло. Почему-то в итоге некоторые элементы массива оказываются "пропущенными" и в итоге дальнейшая обработка

K>данных из этого массива происходит некорректно.

Насколько я понимаю, все должно быть в порядке без всяких синхронизаций.

Аргументация :

Если предположить иное (хоть из-за кешей, хоть из-за чего иного), то

Большой массив — это блок памяти. Тот факт, что он непрерывный — к делу не относится. Если бы он не был непрерывным, ничего бы не менялось в плане этой проблемы.
Тогда, получается, разные потоки могли бы писать в разные блоки памяти, и при этом возникали бы какие-то проблемы. Если бы они возникали, это подорвало бы вообще всю идею потоков — мало ли кто куда пишет.
With best regards
Pavel Dvorkin
Re: Запись в массив double-ов из нескольких потоков
От: zubr Россия  
Дата: 11.05.11 06:01
Оценка: 1 (1) +2
Здравствуйте, kuaw26, Вы писали:

K>пока сделал так: каждый поток имеет свой приватный массив и пишет в него. После того как все потоки окончили работу, я через

K>System.arraycopy() перебрасываю данные в один большой массив.

Скажи, пожалуйста, почему ты считаешь что это плохо?
Мне наоборот кажется этот подход более правильным.
1. проще логика — каждый тред обработчик имеет свой стораж, и его вообще никак не волнует куда и как дальше будут записаны его результаты.
2. локальный массив если он не велик сможет скешироваться (тута я может брешу)
3. нет глобальной переменной YARRR :D

если какая то конвеерная обработка данных, и результатов одного треда хватает — упрощается логика и сам механизм.
Re: Запись в массив double-ов из нескольких потоков
От: Blazkowicz Россия  
Дата: 11.05.11 04:17
Оценка: 1 (1) +1
Здравствуйте, kuaw26, Вы писали:

K>Есть массив double-ов. Есть несколько потоков которые считают функцию качества и результат кладут в этот массив.

K>Каждый поток работает со своей частью массива и по индексам не пересекаются.
K>Можно ли работать с массивом без синхронизации?
K>у меня пока не вышло. Почему-то в итоге некоторые элементы массива оказываются "пропущенными" и в итоге дальнейшая обработка
K>данных из этого массива происходит некорректно.

Странно. Нет никаких предпосылок для того чтоб запись в разные индексы массива была не потокобезопасной.
А чтение точно синхронизированно со всеми записями? Может оно происходит когда ещё не все потоки записали свои значения.
Re: Запись в массив double-ов из нескольких потоков
От: Blazkowicz Россия  
Дата: 11.05.11 12:16
Оценка: 5 (1)
Нагуглилась ссылка по теме. Про volatile вообще и массивы в частности.

http://jeremymanson.blogspot.com/2009/06/volatile-arrays-in-java.html
Re[3]: Запись в массив double-ов из нескольких потоков
От: Donz Россия http://donz-ru.livejournal.com
Дата: 11.05.11 07:07
Оценка: 1 (1)
Здравствуйте, kuaw26, Вы писали:

K>Нагуглил тут идею таки заюзать AtomicLongArray, просто предварительно преобразуя Double.doubleToLongBits(double) и потом обратно.


Если действительно "Основной поток пускал 4 рассчитывающих потока и ждал их окончания.", то не нужны никакие атомики. После окончания работы нить обязана скинуть все, что она закешировала (иначе смысла нет — результат работы уйдет вместе с кешом в GC).
Думаю, что проблема в логике разбиения массива на логические куски.
Можно код?
Re[5]: Запись в массив double-ов из нескольких потоков
От: Blazkowicz Россия  
Дата: 11.05.11 07:13
Оценка: 1 (1)
Здравствуйте, Nicht, Вы писали:

N>В этом случае никто не гарантирует что результат записи потоков в этот массив будет виден в потоке, которые потом это дело читает. Вся запись поихайдет в локальном кэше процессора и без синхронизации кеша все может статься локально. Так что volatile таки нужен.

volatile будет действовать только на переменную, которая ссылается на весь массив. Даже если запись в массив кешировалась на потоке, это было бы важно только если бы происходило параллельное чтение. Чтение (по словам автора) происходит отдельным потоком после того как запись завершилась.
Re[8]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 09:12
Оценка: 1 (1)
Здравствуйте, Donz, Вы писали:

D>Здравствуйте, Nicht, Вы писали:


N>>Ну что значит после все равно не сильно понятно. Если стоит join() то да. Если же какая то другая магия, то не факт.


D>Автор как раз использовал join.


Ну тогда хорошо

N>>Про это сказано в спеке

N>>

N>>The final action in a thread T1 synchronizes-with any action in another thread T2 that detects that T1 has terminated. T2 may accomplish this by calling T1.isAlive() or T1.join().

N>>Тоесть если поток завершился и никто у него не спросил что он завершился, то и изменения могут и не увидеть.

D>Не совсем понял. Нить T1 завершилась, то есть метод run полностью выполнился, сам объект Runnable давно собран GC, как и созданный Thread, а изменения все еще могут быть не доступны другим нитям, пока они явно не спросят, а не умерла ли нить T1?

D>Не могу найти нужный пруфлинк, но это была бы очень странная ситуация.

Ну судя по спеке, да. Если нет синхронайзед ордера, тоесть никто не хочет воспользоваться результатами работы потока, то и результат никто может не увидеть.
Re[6]: Запись в массив double-ов из нескольких потоков
От: abch-98-ru Россия  
Дата: 12.05.11 14:50
Оценка: 1 (1)
K>Насчет неправильности. в джава доке же сказано, что "when all complete" и у всех фьючеров будет "isDone() is true" на кой тогда еще get() делать?
не надо, в случае успешного исполнения, но exception пропустить можно.

K>Потом происходит присваивание в массив и клипс показывает, что как бы присваивания не произошло.... i-ый элемент массива так и остался со значением 0

K>или это не прозошол сброс данных в память?
могло произойти exception.

возможно, была у тебя бага в расчётах, сопровождаемая exception-ом.
она в твоём использовании fork&join "глотается".
в процессе борьбы с непонятками, меняя код, ты заодно и пофиксил либо код расчёта, либо входные данные.
чтоб в следующий раз не мучиться — дёргай get() и обрабатывай exception.
Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 02:35
Оценка:
Есть массив double-ов. Есть несколько потоков которые считают функцию качества и результат кладут в этот массив.
Каждый поток работает со своей частью массива и по индексам не пересекаются.
Можно ли работать с массивом без синхронизации?

у меня пока не вышло. Почему-то в итоге некоторые элементы массива оказываются "пропущенными" и в итоге дальнейшая обработка
данных из этого массива происходит некорректно.

пока сделал так: каждый поток имеет свой приватный массив и пишет в него. После того как все потоки окончили работу, я через
System.arraycopy() перебрасываю данные в один большой массив.
Re: Запись в массив double-ов из нескольких потоков
От: abch-98-ru Россия  
Дата: 11.05.11 05:03
Оценка:
K>Есть массив double-ов. Есть несколько потоков которые считают функцию качества и результат кладут в этот массив.
K>Каждый поток работает со своей частью массива и по индексам не пересекаются.
K>Можно ли работать с массивом без синхронизации?

гарантии видимости(чтения) при записи в массив из разных потоков отсуствуют (
для лонгов и объектов в стандартной библиотеке есть AtomicLongArray и AtomicReferenceArray (всё lock-free), соответственно.
в качестве конструктива — можно адаптироваться к кому-то из них или написать своё на volatile/lock/synchronized.
вам нужна только видимость, т.что volatile-ов должно хватить.
Re[2]: Запись в массив double-ов из нескольких потоков
От: abch-98-ru Россия  
Дата: 11.05.11 05:07
Оценка:
Здравствуйте, abch-98-ru, Вы писали:
K>>Можно ли работать с массивом без синхронизации?
A9R>гарантии видимости(чтения) при записи в массив из разных потоков отсуствуют (
fix: если поток читающий != потоку записывающему
Re[2]: Запись в массив double-ов из нескольких потоков
От: elmal  
Дата: 11.05.11 05:40
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Странно. Нет никаких предпосылок для того чтоб запись в разные индексы массива была не потокобезопасной.

Вообще, если копать очень глубоко, то предпосылки есть. Процессоры многоядерные, с отдельным кешем под каждое ядро. В одном потоке меняют, в другом не факт что видно (хоть я и далек от беталей работы процессоров, но здравый смысл подсказывает, что в целях оптимизации синхронизацию кешей при каждой записи могли не делать, или делать отложенно). Тут просто примитивы могут не быть видны без volatile, а с массивами то еще сложнее вроде ситуация.
Re: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 05:59
Оценка:
elmal>Вообще, если копать очень глубоко, то предпосылки есть. Процессоры многоядерные, с отдельным кешем под каждое ядро. В одном потоке меняют, в другом не факт что видно (хоть я и далек от беталей работы процессоров, но здравый смысл подсказывает, что в целях оптимизации синхронизацию кешей при каждой записи могли не делать, или делать отложенно). Тут просто примитивы могут не быть видны без volatile, а с массивами то еще сложнее вроде ситуация.

Таки да тест делался на 4-х ядерном Core Quad 9500.
Основной поток пускал 4 рассчитывающих потока и ждал их окончания.
Использовал Fork/Join который обещают в 7-ой джаве добавить, но он уже и в 6-ке доступен.

abch-98-ru> гарантии видимости(чтения) при записи в массив из разных потоков отсуствуют (
для лонгов и объектов в стандартной библиотеке есть AtomicLongArray и AtomicReferenceArray (всё lock-free), соответственно.
в качестве конструктива — можно адаптироваться к кому-то из них или написать своё на volatile/lock/synchronized.
вам нужна только видимость, т.что volatile-ов должно хватить.

Это я уже то же нагуглил про AtomicXXXArray, но для double-ов нет готовой реализации.
Попробовать написать AtomicDoubleArray — ???
Нагуглил вот такую дискуссию:

> Is there a reason util.concurrent has no AtomicDoubleArray class?

Yes because there are no generally available atomic instructions for
operating on floating-point values. So basically your only option is
synchronization using locks.

> There is this throw-away line at the end of the package docs:

> "You can also hold floats using Float.floatToIntBits and
> Float.intBitstoFloat conversions, and doubles using
> Double.doubleToLongBits and Double.longBitsToDouble conversions."
> But that doesn't seem to help if you want to use the atomic add
> methods

Right, these techniques allow you to hold float bits and do atomic get/set
and CAS but not general arithmetic — because again there are no atomic
instructions for doing that.

> Is there another way to do atomic double array ops that doesn't

> involve using synchronize?

Nope — locking is really your only option.
Re[2]: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 06:13
Оценка:
Здравствуйте, zubr, Вы писали:

Z>Скажи, пожалуйста, почему ты считаешь что это плохо?

Z>Мне наоборот кажется этот подход более правильным.
Z>1. проще логика — каждый тред обработчик имеет свой стораж, и его вообще никак не волнует куда и как дальше будут записаны его результаты.
Z>2. локальный массив если он не велик сможет скешироваться (тута я может брешу)
Z>3. нет глобальной переменной YARRR :D
Z>если какая то конвеерная обработка данных, и результатов одного треда хватает — упрощается логика и сам механизм.

Ну скажем так, в некоторых ситуациях — плохо.
Так как идет удвоенный расход памяти: большой массив в основном потоке и еще столько же, но пропорциональными кусками в потоках обработчиках.

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

ну и я просто хотел для себя выяснить, что же не так с массивом double-ов, так сказать, закрыть пробел в своих познаниях.
Re[2]: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 06:18
Оценка:
Нагуглил тут идею таки заюзать AtomicLongArray, просто предварительно преобразуя Double.doubleToLongBits(double) и потом обратно.
Re[3]: Запись в массив double-ов из нескольких потоков
От: abch-98-ru Россия  
Дата: 11.05.11 06:53
Оценка:
K>Но подумав хорошенько куда моя программа будет расти, а расти она будет в сторону запуска вчисляющих потоков на кластре,
K>то в итоге все равно бы пришлось каждому вычислителю выделять свой сторадж для локальных вычислений, а потом просчитанный кусок отдавать
K>главному процессу.
если мы уж про архитектуру... map/reduce не крутили для вашей задачи?

K>ну и я просто хотел для себя выяснить, что же не так с массивом double-ов, так сказать, закрыть пробел в своих познаниях.

вроде уже обсудили.
Re[3]: Запись в массив double-ов из нескольких потоков
От: Donz Россия http://donz-ru.livejournal.com
Дата: 11.05.11 06:56
Оценка:
Здравствуйте, elmal, Вы писали:

B>>Странно. Нет никаких предпосылок для того чтоб запись в разные индексы массива была не потокобезопасной.

E>Вообще, если копать очень глубоко, то предпосылки есть. Процессоры многоядерные, с отдельным кешем под каждое ядро. В одном потоке меняют, в другом не факт что видно. Тут просто примитивы могут не быть видны без volatile, а с массивами то еще сложнее вроде ситуация.

А что там сложного? Массив инициализируется один раз и до запуска нитей-счетчиков, вся необходимая память выделяется сразу же. Взять недоинициализированный массив ни одна из нитей не может. Границы индексов у каждой нити свои и тоже рассчитываются до начала их работы. Основная нить начинает работу с массивом только после окончания работы всех нитей-счетчиков. То есть, все данные, касающиеся массива и его границ, известны до запуска нитей-счетчиков, так что никакого фейла из-за отсутствия volatile быть не может.
Не вижу ни одной причины, по которой может происходить ошибка из-за многопоточной среды.
Думаю, это скорее логическая ошибка в рассчетах или в распределении области для хранения данных.
Re[4]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 07:07
Оценка:
Здравствуйте, Donz, Вы писали:


D>А что там сложного? Массив инициализируется один раз и до запуска нитей-счетчиков, вся необходимая память выделяется сразу же. Взять недоинициализированный массив ни одна из нитей не может. Границы индексов у каждой нити свои и тоже рассчитываются до начала их работы. Основная нить начинает работу с массивом только после окончания работы всех нитей-счетчиков. То есть, все данные, касающиеся массива и его границ, известны до запуска нитей-счетчиков, так что никакого фейла из-за отсутствия volatile быть не может.

D>Не вижу ни одной причины, по которой может происходить ошибка из-за многопоточной среды.
D>Думаю, это скорее логическая ошибка в рассчетах или в распределении области для хранения данных.

В этом случае никто не гарантирует что результат записи потоков в этот массив будет виден в потоке, которые потом это дело читает. Вся запись поихайдет в локальном кэше процессора и без синхронизации кеша все может статься локально. Так что volatile таки нужен.
Re[4]: Запись в массив double-ов из нескольких потоков
От: Blazkowicz Россия  
Дата: 11.05.11 07:12
Оценка:
Здравствуйте, abch-98-ru, Вы писали:

K>>ну и я просто хотел для себя выяснить, что же не так с массивом double-ов, так сказать, закрыть пробел в своих познаниях.

A9R>вроде уже обсудили.
Нет, не обсудили.
Re[3]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 07:13
Оценка:
Здравствуйте, kuaw26, Вы писали:

K>Здравствуйте, zubr, Вы писали:


Z>>Скажи, пожалуйста, почему ты считаешь что это плохо?

Z>>Мне наоборот кажется этот подход более правильным.
Z>>1. проще логика — каждый тред обработчик имеет свой стораж, и его вообще никак не волнует куда и как дальше будут записаны его результаты.
Z>>2. локальный массив если он не велик сможет скешироваться (тута я может брешу)
Z>>3. нет глобальной переменной YARRR :D
Z>>если какая то конвеерная обработка данных, и результатов одного треда хватает — упрощается логика и сам механизм.

K>Ну скажем так, в некоторых ситуациях — плохо.

K>Так как идет удвоенный расход памяти: большой массив в основном потоке и еще столько же, но пропорциональными кусками в потоках обработчиках.

А может есть возможность сихронизировать данные в большой массив последовательно. Ну тоесть локальные массивы сделать небольшими и сливать их по мере наполнения. В таком случае можно подобрать размер этих массивов так, что бы они были равны или кратны кэш линии процессора, что хорошо скажется на производительности. Правда это надо будет параметризовать в зависимости от железа.
Re[6]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 07:26
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, Nicht, Вы писали:


N>>В этом случае никто не гарантирует что результат записи потоков в этот массив будет виден в потоке, которые потом это дело читает. Вся запись поихайдет в локальном кэше процессора и без синхронизации кеша все может статься локально. Так что volatile таки нужен.

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

Ну если гарантирован syncronized order между записью и чтение, то конечно все пучком. Этого можно добится несколькими способами, вызвать Thread.join() на пример. В спеке все это сказано. Однако если ты юзаешь ThreadPool то поток как бы и не завершится и будет alive, и там нужно делать синхроназед ордер вручную. Стандартный способ это свезка записи и чтения в другую volatile переменную, а между ними свое действие. Ну или вопользоваться FutureTask, там сделано тоже самое через AbstractQueuedSynchronizer.
Re[5]: Запись в массив double-ов из нескольких потоков
От: Donz Россия http://donz-ru.livejournal.com
Дата: 11.05.11 07:35
Оценка:
Здравствуйте, Nicht, Вы писали:

N>В этом случае никто не гарантирует что результат записи потоков в этот массив будет виден в потоке, которые потом это дело читает. Вся запись поихайдет в локальном кэше процессора и без синхронизации кеша все может статься локально. Так что volatile таки нужен.


ТС ниже уточнил, что основная нить начинает обработку массива после окончания работы нитей-счетчиков. Кеши должны гарантировано сброситься.
Re[6]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 07:55
Оценка:
Здравствуйте, Donz, Вы писали:

D>Здравствуйте, Nicht, Вы писали:


N>>В этом случае никто не гарантирует что результат записи потоков в этот массив будет виден в потоке, которые потом это дело читает. Вся запись поихайдет в локальном кэше процессора и без синхронизации кеша все может статься локально. Так что volatile таки нужен.


D>ТС ниже уточнил, что основная нить начинает обработку массива после окончания работы нитей-счетчиков. Кеши должны гарантировано сброситься.


Ну что значит после все равно не сильно понятно. Если стоит join() то да. Если же какая то другая магия, то не факт.

Про это сказано в спеке

The final action in a thread T1 synchronizes-with any action in another thread T2 that detects that T1 has terminated. T2 may accomplish this by calling T1.isAlive() or T1.join().

Тоесть если поток завершился и никто у него не спросил что он завершился, то и изменения могут и не увидеть.
Re[4]: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 08:27
Оценка:
Здравствуйте, Donz, Вы писали:

D>Если действительно "Основной поток пускал 4 рассчитывающих потока и ждал их окончания.", то не нужны никакие атомики. После окончания работы нить обязана скинуть все, что она закешировала (иначе смысла нет — результат работы уйдет вместе с кешом в GC).

D>Думаю, что проблема в логике разбиения массива на логические куски.
D>Можно код?

блин странная фигня.... 3 дня парился, а сейчас не воспроизводится...
я в общем то примерно так и рассуждал сначал, но потом стал сомневаться....

сделал простенький тест-кейс. Fork/Join брал у ее создателя Дуга Ли: тут
public class Processor implements Callable<Boolean>
{
 private final int from;
 private final int to;
 private final double[] ii;
 
 public Processor(int from, int to, double[] ii)
 {
  this.from = from;
  this.to = to;
  this.ii = ii;
 }

 @Override
 public Boolean call()
 {
  for (int i = from; i < to; i++)
  {
   // просто хоть что-то посчитать, имитация реальных вычислений
   for (int j = from; j < to; j++)
    ii[i] += j;
  }
  
  return (Boolean.TRUE);
 }
}
----------------
import jsr166y.ForkJoinPool;

public class ArrayOfDoublesTest
{
 private final double[] ii;
 
 public ArrayOfDoublesTest(int arraySize)
 {
  ii = new double[arraySize];
 }
 
 public void process(int parallelism)
 {
  System.out.printf("Parallelism = %d%n", parallelism);
  
  Arrays.fill(ii, 0);
  
  List<Processor> tasks = new ArrayList<Processor>(parallelism);
  int delta = ii.length / parallelism;
  int lo = 0;
  for (int i = 0; i < parallelism; i++)
  {
   int hi = lo + delta;
   
   // гарантируем что для в последний кусок попадет все что осталось
   if (i == (parallelism-1))
   {
    hi = ii.length;
   }

   tasks.add(new Processor(lo, hi, ii));
  }
  
  // вызываем все задачи
  ForkJoinPool pool = new ForkJoinPool(parallelism);
  pool.invokeAll(tasks);
  
  for (int i = 0; i < ii.length; i++)
  {
   if (ii[i] == 0)
    System.out.printf("Failed for ii[%d]!%n", i);
  }
 }
 
 /**
  * @param args
  */
 public static void main(String[] args)
 {
  ArrayOfDoublesTest test = new ArrayOfDoublesTest(50000);
  test.process(1);
  test.process(2);
  test.process(3);
  test.process(4);
 }
}
Re[2]: Запись в массив double-ов из нескольких потоков
От: zubr Россия  
Дата: 11.05.11 08:32
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Большой массив — это блок памяти. Тот факт, что он непрерывный — к делу не относится. Если бы он не был непрерывным, ничего бы не менялось в плане этой проблемы.

PD>Тогда, получается, разные потоки могли бы писать в разные блоки памяти, и при этом возникали бы какие-то проблемы. Если бы они возникали, это подорвало бы вообще всю идею потоков — мало ли кто куда пишет.

В том то и проблема если массив это кусок, и кешируется он кусками — то получается проблема синхронизации и кешей.
Re[7]: Запись в массив double-ов из нескольких потоков
От: Donz Россия http://donz-ru.livejournal.com
Дата: 11.05.11 09:05
Оценка:
Здравствуйте, Nicht, Вы писали:

N>Ну что значит после все равно не сильно понятно. Если стоит join() то да. Если же какая то другая магия, то не факт.


Автор как раз использовал join.

N>Про это сказано в спеке

N>

N>The final action in a thread T1 synchronizes-with any action in another thread T2 that detects that T1 has terminated. T2 may accomplish this by calling T1.isAlive() or T1.join().

N>Тоесть если поток завершился и никто у него не спросил что он завершился, то и изменения могут и не увидеть.

Не совсем понял. Нить T1 завершилась, то есть метод run полностью выполнился, сам объект Runnable давно собран GC, как и созданный Thread, а изменения все еще могут быть не доступны другим нитям, пока они явно не спросят, а не умерла ли нить T1?
Не могу найти нужный пруфлинк, но это была бы очень странная ситуация.
Re[9]: Запись в массив double-ов из нескольких потоков
От: Donz Россия http://donz-ru.livejournal.com
Дата: 11.05.11 09:13
Оценка:
Здравствуйте, Nicht, Вы писали:

D>>Не совсем понял. Нить T1 завершилась, то есть метод run полностью выполнился, сам объект Runnable давно собран GC, как и созданный Thread, а изменения все еще могут быть не доступны другим нитям, пока они явно не спросят, а не умерла ли нить T1?

D>>Не могу найти нужный пруфлинк, но это была бы очень странная ситуация.
N>Ну судя по спеке, да. Если нет синхронайзед ордера, тоесть никто не хочет воспользоваться результатами работы потока, то и результат никто может не увидеть.

Да, ситуация запуска нитей без синхронизации контекста сама по себе странная, но подобное поведение после смерти нити еще более страннее.
Re[3]: Запись в массив double-ов из нескольких потоков
От: Pavel Dvorkin Россия  
Дата: 11.05.11 09:34
Оценка:
Здравствуйте, zubr, Вы писали:

Z>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Большой массив — это блок памяти. Тот факт, что он непрерывный — к делу не относится. Если бы он не был непрерывным, ничего бы не менялось в плане этой проблемы.

PD>>Тогда, получается, разные потоки могли бы писать в разные блоки памяти, и при этом возникали бы какие-то проблемы. Если бы они возникали, это подорвало бы вообще всю идею потоков — мало ли кто куда пишет.

Z>В том то и проблема если массив это кусок, и кешируется он кусками — то получается проблема синхронизации и кешей.


А если не один массив, а несколько ,и в каждый пишет свой поток ?
А если вообще разные структуры данных, и в каждую из них пишет свой поток ?
Так мы можем дойти до требования какого-то специального размещения данных для потоков, что будет совсем уж ни в какие ворота.
With best regards
Pavel Dvorkin
Re[5]: Запись в массив double-ов из нескольких потоков
От: abch-98-ru Россия  
Дата: 11.05.11 09:47
Оценка:
A9R>>вроде уже обсудили.
B>Нет, не обсудили.
Ещё актуально? Если есть вопрос — сформулируйте, пожалуйста.
Re[6]: Запись в массив double-ов из нескольких потоков
От: Blazkowicz Россия  
Дата: 11.05.11 10:11
Оценка:
Здравствуйте, abch-98-ru, Вы писали:

A9R>>>вроде уже обсудили.

B>>Нет, не обсудили.
A9R>Ещё актуально? Если есть вопрос — сформулируйте, пожалуйста.
Какие существуют предпосылки к тому запись в разные массивы была не потокобезопасной. Может ли массив (достаточно большой) целиком кешироваться в памяти\реестрах выделеных потоку.
Re[7]: Запись в массив double-ов из нескольких потоков
От: Pavel Dvorkin Россия  
Дата: 11.05.11 10:21
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, abch-98-ru, Вы писали:


A9R>>>>вроде уже обсудили.

B>>>Нет, не обсудили.
A9R>>Ещё актуально? Если есть вопрос — сформулируйте, пожалуйста.
B>Какие существуют предпосылки к тому запись в разные массивы была не потокобезопасной. Может ли массив (достаточно большой) целиком кешироваться в памяти\реестрах выделеных потоку.

А чем, простите, разные массивы отличаются от одного массива ?

Сорри, перейду на С


union A {
 struct A2
{ int a[10];
  int b[10];
};
int c[20];
};


Это один или два массива ? Можно считать и так, и так.

И вообще, с каких это пор расположение объектов в виртуальной памяти на что-то влияет ?
With best regards
Pavel Dvorkin
Re[8]: Запись в массив double-ов из нескольких потоков
От: Blazkowicz Россия  
Дата: 11.05.11 10:39
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Это один или два массива ? :-) Можно считать и так, и так.

PD>И вообще, с каких это пор расположение объектов в виртуальной памяти на что-то влияет ?
Это здесь к чему? Вот есть ключевое слово volatile. Оно применяется к переменной-полю. Если мы спроецируем абстракцию, то элемент массива это переменная. Она работает так же как volatile поле, или иначе?
Re[9]: Запись в массив double-ов из нескольких потоков
От: Pavel Dvorkin Россия  
Дата: 11.05.11 10:59
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Это один или два массива ? Можно считать и так, и так.

PD>>И вообще, с каких это пор расположение объектов в виртуальной памяти на что-то влияет ?
B>Это здесь к чему? Вот есть ключевое слово volatile. Оно применяется к переменной-полю. Если мы спроецируем абстракцию, то элемент массива это переменная. Она работает так же как volatile поле, или иначе?

При чем тут volatile ? Его употребляют, когда надо проинформировать компилятор, что переменную надо брать всегда из памяти, а не из регистра, так как она может быть изменена в другом месте. Где тут переменные (или элементы массива), которые могут измениться в другом месте, если по условиям ТС каждый поток работает строго со своими элементами ?

А к тому это здесь, что заведи один массив или несколько массивов — это ничего не меняет в плане доступа к ним потоков, если потоки не обращаются к одним и тем же элементам.
With best regards
Pavel Dvorkin
Re[7]: Запись в массив double-ов из нескольких потоков
От: abch-98-ru Россия  
Дата: 11.05.11 11:04
Оценка:
A9R>>>>вроде уже обсудили.
B>>>Нет, не обсудили.
A9R>>Ещё актуально? Если есть вопрос — сформулируйте, пожалуйста.
B>Какие существуют предпосылки к тому запись в разные массивы была не потокобезопасной.
если программа только пишет в разные массивы — то race-ов нет, всё потокобезопасно.
если и читает, то есть нюансы:
если существуют два action-а не под happens-before над variable(term variable to refer to both fields and array elements)и один из них write, то это race и, стал быть, программа не потокобезопасна.

B>Может ли массив (достаточно большой) целиком кешироваться в памяти\реестрах выделеных потоку.

кэширование не обсуждается в jls3(только в jls2) так что если не писать java-код под конкретную jvm — версия — архитектура, то это(может или нет кэшироваться) неопределено и может быть изменено.
Re[8]: Запись в массив double-ов из нескольких потоков
От: Blazkowicz Россия  
Дата: 11.05.11 11:07
Оценка:
Здравствуйте, abch-98-ru, Вы писали:

A9R>если программа только пишет в разные массивы — то race-ов нет, всё потокобезопасно.

В один массив. Разные индексы.
И если такие безопасно, то осталось разобраться, почему у автора это не так.
Re[9]: Запись в массив double-ов из нескольких потоков
От: abch-98-ru Россия  
Дата: 11.05.11 11:11
Оценка:
A9R>>если программа только пишет в разные массивы — то race-ов нет, всё потокобезопасно.
B>В один массив. Разные индексы.
в твоём вопросе было
B>Какие существуют предпосылки к тому запись в разные массивы была не потокобезопасной.
но даже с изменённым условием, при наличии только записи всё будет потокобезопасно.

B>И если такие безопасно, то осталось разобраться, почему у автора это не так.

у автора есть, по крайней мере, чтение.
Re[10]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 11:17
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Blazkowicz, Вы писали:


B>>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>>Это один или два массива ? Можно считать и так, и так.

PD>>>И вообще, с каких это пор расположение объектов в виртуальной памяти на что-то влияет ?
B>>Это здесь к чему? Вот есть ключевое слово volatile. Оно применяется к переменной-полю. Если мы спроецируем абстракцию, то элемент массива это переменная. Она работает так же как volatile поле, или иначе?

PD>При чем тут volatile ? Его употребляют, когда надо проинформировать компилятор, что переменную надо брать всегда из памяти, а не из регистра, так как она может быть изменена в другом месте. Где тут переменные (или элементы массива), которые могут измениться в другом месте, если по условиям ТС каждый поток работает строго со своими элементами ?


PD>А к тому это здесь, что заведи один массив или несколько массивов — это ничего не меняет в плане доступа к ним потоков, если потоки не обращаются к одним и тем же элементам.


Это все устарело с выходом JSR 133 (Java Memory Model).
Re[10]: Запись в массив double-ов из нескольких потоков
От: Blazkowicz Россия  
Дата: 11.05.11 11:24
Оценка:
Здравствуйте, abch-98-ru, Вы писали:

B>>В один массив. Разные индексы.

A9R>в твоём вопросе было
B>>Какие существуют предпосылки к тому запись в разные массивы была не потокобезопасной.

Опечатался. :shuffle:
Re[11]: Запись в массив double-ов из нескольких потоков
От: Pavel Dvorkin Россия  
Дата: 11.05.11 11:26
Оценка:
Здравствуйте, Nicht, Вы писали:


PD>>А к тому это здесь, что заведи один массив или несколько массивов — это ничего не меняет в плане доступа к ним потоков, если потоки не обращаются к одним и тем же элементам.


N>Это все устарело с выходом JSR 133 (Java Memory Model).


Речь идет о доступе к разным байтам (словам и т.д.) памяти. Потоки не имеют общих данных.
With best regards
Pavel Dvorkin
Re[12]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 11:38
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Nicht, Вы писали:



PD>>>А к тому это здесь, что заведи один массив или несколько массивов — это ничего не меняет в плане доступа к ним потоков, если потоки не обращаются к одним и тем же элементам.


N>>Это все устарело с выходом JSR 133 (Java Memory Model).


PD>Речь идет о доступе к разным байтам (словам и т.д.) памяти. Потоки не имеют общих данных.


Где идет речь?
Re[9]: Запись в массив double-ов из нескольких потоков
От: Donz Россия http://donz-ru.livejournal.com
Дата: 11.05.11 11:47
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

PD>>Это один или два массива ? Можно считать и так, и так.

PD>>И вообще, с каких это пор расположение объектов в виртуальной памяти на что-то влияет ?
B>Это здесь к чему? Вот есть ключевое слово volatile. Оно применяется к переменной-полю. Если мы спроецируем абстракцию, то элемент массива это переменная. Она работает так же как volatile поле, или иначе?

Очень не уверен, что это обобщение правильно. С точки зрения языка это совершенно разные контейнеры памяти. И на уровне байт-кода применяются разные инструкции для чтения и записи данных в поле и в ячейку массива.
ИМХО, сам массив не может кешироваться нитью. Кешироваться могут только поля (примитивные типы или ссылки на объекты).
Re[13]: Запись в массив double-ов из нескольких потоков
От: Pavel Dvorkin Россия  
Дата: 11.05.11 11:56
Оценка:
Здравствуйте, Nicht, Вы писали:

N>>>Это все устарело с выходом JSR 133 (Java Memory Model).


PD>>Речь идет о доступе к разным байтам (словам и т.д.) памяти. Потоки не имеют общих данных.


N>Где идет речь?


В задаче ТС.
With best regards
Pavel Dvorkin
Re[10]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 11:57
Оценка:
Здравствуйте, Donz, Вы писали:

D>ИМХО, сам массив не может кешироваться нитью. Кешироваться могут только поля (примитивные типы или ссылки на объекты).


Есть мнение что это не так. Вот тут человек матрицы перемножал. Так вот оказкалось быстрее транспонировать вторую матрицу и перемножать не строка на столбец а строку на строку как раз из за того что куски одномерного массива префетчатся в кэш линию. Причем выигрыш по времени был 230%.
Re[14]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 12:01
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Nicht, Вы писали:


N>>>>Это все устарело с выходом JSR 133 (Java Memory Model).


PD>>>Речь идет о доступе к разным байтам (словам и т.д.) памяти. Потоки не имеют общих данных.


N>>Где идет речь?


PD>В задаче ТС.


В данной задаче проблема не в записи. Там нет рейса, так как потоки пишут в разные места и не пересекаются. Проблема могла быть как раз с видимостью резальтатов их работы в потоке, который читает данные из общего моссива. Если не сделать синхроназед ордер между писателями и читателем, читатель может просто не увидеть что сделал писатель и в итоге получить массив с почти проихвольным наполнением. Но вроде из исходника видно что там все нормально.
Re[15]: Запись в массив double-ов из нескольких потоков
От: Pavel Dvorkin Россия  
Дата: 11.05.11 12:04
Оценка:
Здравствуйте, Nicht, Вы писали:

N>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Здравствуйте, Nicht, Вы писали:


N>>>>>Это все устарело с выходом JSR 133 (Java Memory Model).


PD>>>>Речь идет о доступе к разным байтам (словам и т.д.) памяти. Потоки не имеют общих данных.


N>>>Где идет речь?


PD>>В задаче ТС.


N>В данной задаче проблема не в записи. Там нет рейса, так как потоки пишут в разные места и не пересекаются. Проблема могла быть как раз с видимостью резальтатов их работы в потоке, который читает данные из общего моссива. Если не сделать синхроназед ордер между писателями и читателем, читатель может просто не увидеть что сделал писатель и в итоге получить массив с почти проихвольным наполнением. Но вроде из исходника видно что там все нормально.


Из сообщения ТС

ТС>Почему-то в итоге некоторые элементы массива


В итоге — надо понимать как "после того, как все потоки отработали", так (иначе какой же это итог ?). Так что поток, который читает данные из общего массива, работает тогда, когда вся эта деятельность уже закончена.
With best regards
Pavel Dvorkin
Re[11]: Запись в массив double-ов из нескольких потоков
От: Donz Россия http://donz-ru.livejournal.com
Дата: 11.05.11 12:09
Оценка:
Здравствуйте, Nicht, Вы писали:

D>>ИМХО, сам массив не может кешироваться нитью. Кешироваться могут только поля (примитивные типы или ссылки на объекты).

N>Есть мнение что это не так. Вот тут человек матрицы перемножал. Так вот оказкалось быстрее транспонировать вторую матрицу и перемножать не строка на столбец а строку на строку как раз из за того что куски одномерного массива префетчатся в кэш линию. Причем выигрыш по времени был 230%.

Не настолько плотно знаком с моделью памяти x86 и явовской, но навряд ли понятие кеширования нитью в яве равнозначно понятию кеширования данных на уровне процессора. Если какой-то кусок памяти отображен на кеш, то является ли это отображение валидным только для одного ядра или процесса, или сразу для всех и полностью для них прозрачно?
Если кеширование в яве равнозначно кешированию процессором, то получается, что мы не можем равноценно управлять процессом синхронизации данных из явы, так как для элементов массива отсутствует возможность сделать их volatile.
Re[16]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 12:10
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:


PD>В итоге — надо понимать как "после того, как все потоки отработали", так (иначе какой же это итог ?). Так что поток, который читает данные из общего массива, работает тогда, когда вся эта деятельность уже закончена.


Ну я мысли не умею читать так что решил уточнить. Так же уже обсуждалось что сентенция "после того, как все потоки отработали" тоже ничего не говорит о наличии синхронайзед ордера между записью и чтением.
Re[12]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 12:18
Оценка:
Здравствуйте, Donz, Вы писали:

D>Здравствуйте, Nicht, Вы писали:


D>>>ИМХО, сам массив не может кешироваться нитью. Кешироваться могут только поля (примитивные типы или ссылки на объекты).

N>>Есть мнение что это не так. Вот тут человек матрицы перемножал. Так вот оказкалось быстрее транспонировать вторую матрицу и перемножать не строка на столбец а строку на строку как раз из за того что куски одномерного массива префетчатся в кэш линию. Причем выигрыш по времени был 230%.

D>Не настолько плотно знаком с моделью памяти x86 и явовской, но навряд ли понятие кеширования нитью в яве равнозначно понятию кеширования данных на уровне процессора. Если какой-то кусок памяти отображен на кеш, то является ли это отображение валидным только для одного ядра или процесса, или сразу для всех и полностью для них прозрачно?


Вообще говоря, он не валиден ни для кого. Для этого есть system bus и протоколы валидации кеша. Современное железо обычно при валидации кеша оперируют не конкретным регистром а так называемой cache line. Это, грубо говоря, массив. По этому понятно, что выгодно валидейтить кэш когда у тебя не один регистр в линии проапдейтился а как можно больше.

D>Если кеширование в яве равнозначно кешированию процессором, то получается, что мы не можем равноценно управлять процессом синхронизации данных из явы, так как для элементов массива отсутствует возможность сделать их volatile.


В JMM вообще ничего не сказано про кеширование. Все это отдается на откуп оптимизирующему компилятору, а он будет это далеть согласно железной платформы. То что указало в статье в принципе карактерно для х86. Конечно если взять регистровые процессоры, то там все будет не так.
Re: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 12:19
Оценка:
Прочитал всю ветку. Что-то мнения разошлись.

Еще раз опишу свою задачу:
Есть пул потоков кратный числу ядер в процессоре.
Основной поток запускает вычислительные потоки и ждет когда они отработают.
В каждом потоке тупо в цикле вызывается расчет математической функции и результат записывается в массив.
массив double-ов объявлен как final и создан в конструкторе.
Использую Fork/Join.

Nicht>Ну если гарантирован syncronized order между записью и чтение, то конечно все пучком.

Nicht>Этого можно добится несколькими способами, вызвать Thread.join() на пример. В спеке все это сказано.
Nicht>Однако если ты юзаешь ThreadPool то поток как бы и не завершится и будет alive, и там нужно делать синхроназед ордер вручную.

У меня как раз ThreadPool. Как мне синхронизовать в ручную?
И еще дайте сслку на спеку хочу сам почитать.
Re[2]: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 12:23
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Нагуглилась ссылка по теме. Про volatile вообще и массивы в частности.

B>http://jeremymanson.blogspot.com/2009/06/volatile-arrays-in-java.html

Хороший блог, как раз одного из авторов jsr-133
Почитаю и в закладки однозначно
Re[2]: Запись в массив double-ов из нескольких потоков
От: Blazkowicz Россия  
Дата: 11.05.11 12:27
Оценка:
Здравствуйте, kuaw26, Вы писали:

K>Есть пул потоков кратный числу ядер в процессоре.

K>Основной поток запускает вычислительные потоки и ждет когда они отработают.
K>В каждом потоке тупо в цикле вызывается расчет математической функции и результат записывается в массив.
K>массив double-ов объявлен как final и создан в конструкторе.
K>Использую Fork/Join.
Встречных вопроса два.
— Есть ли тестовый код демонстрирующий проблему?
— Какие ещё есть гарантии что проблема вызвана именно записью в массив а не другой логикой?

K>И еще дайте сслку на спеку хочу сам почитать.

http://java.sun.com/docs/books/jls/
Странно что ссылка не на оракл ещё работает.
Re[2]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 12:36
Оценка:
Здравствуйте, kuaw26, Вы писали:

K>Прочитал всю ветку. Что-то мнения разошлись.


K>Еще раз опишу свою задачу:

K>Есть пул потоков кратный числу ядер в процессоре.
K>Основной поток запускает вычислительные потоки и ждет когда они отработают.
K>В каждом потоке тупо в цикле вызывается расчет математической функции и результат записывается в массив.
K>массив double-ов объявлен как final и создан в конструкторе.
K>Использую Fork/Join.

Тут надо читать доку по Fork/Join. У меня под рукой нет. По идее на методе ForkJoinPool.invokeAll() должно быть написано про синхронизацию памяти.

Nicht>>Ну если гарантирован syncronized order между записью и чтение, то конечно все пучком.

Nicht>>Этого можно добится несколькими способами, вызвать Thread.join() на пример. В спеке все это сказано.
Nicht>>Однако если ты юзаешь ThreadPool то поток как бы и не завершится и будет alive, и там нужно делать синхроназед ордер вручную.

K>У меня как раз ThreadPool. Как мне синхронизовать в ручную?

K>И еще дайте сслку на спеку хочу сам почитать.

Threads and Locks
Re[3]: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 12:45
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Встречных вопроса два.

B>- Есть ли тестовый код демонстрирующий проблему?
Я выше приводил код, но он успешно работает, и проблему не демонстрирует.
Моя реальная прога устроена так же как и пример, не намного сложнее.
Если воспроизведется, то выложу весь код.

B>- Какие ещё есть гарантии что проблема вызвана именно записью в массив а не другой логикой?

Да нету никаких гарантий. У меня почему то перестало воспроизводится....
Хотя до этого 3 дня мозг парил.

B>http://java.sun.com/docs/books/jls/

Скачал. Почитаю. Можно читать только 3-ю редакцию? Или надо и 2-юу с 1-ой читать?
Re[3]: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 12:59
Оценка:
N>Тут надо читать доку по Fork/Join. У меня под рукой нет. По идее на методе ForkJoinPool.invokeAll() должно быть написано про синхронизацию памяти.
ForkJoinPool.invokeAll()

Executes the given tasks, returning a list of Futures holding their status and results when all complete.
Future.isDone() is true for each element of the returned list.
Note that a completed task could have terminated either normally or by throwing an exception.
The results of this method are undefined if the given collection is modified while this operation is in progress.

Про память особо ничего не сказано, но сказано что метод вернет управление, после завершения всех задач.
Сбросят ли потоки в пуле свои кэши в этот момент или нет?
Re[17]: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 13:03
Оценка:
Здравствуйте, Nicht, Вы писали:

N>Ну я мысли не умею читать так что решил уточнить. Так же уже обсуждалось что сентенция "после того, как все потоки отработали" тоже ничего не говорит о наличии синхронайзед ордера между записью и чтением.


А как обеспечить этот синхронайзед ордер? как я уже писал в одном из постов у меня пул потоков.
Может действительно дело в пуле потоков? типа JVM считает их живыми и не скидывает кэши или еще что?
Re[4]: Запись в массив double-ов из нескольких потоков
От: Nicht Россия  
Дата: 11.05.11 13:39
Оценка:
Здравствуйте, kuaw26, Вы писали:

N>>Тут надо читать доку по Fork/Join. У меня под рукой нет. По идее на методе ForkJoinPool.invokeAll() должно быть написано про синхронизацию памяти.

K>ForkJoinPool.invokeAll()

K>Executes the given tasks, returning a list of Futures holding their status and results when all complete.

K>Future.isDone() is true for each element of the returned list.
K>Note that a completed task could have terminated either normally or by throwing an exception.
K>The results of this method are undefined if the given collection is modified while this operation is in progress.

K>Про память особо ничего не сказано, но сказано что метод вернет управление, после завершения всех задач.

K>Сбросят ли потоки в пуле свои кэши в этот момент или нет?

Ну судя по тому что он возвращает Future, то твой код не правильный потому что не вызывает у этих future get() и тем самым вообще не дожидается завершения выполнения.
После беглого просмотра документации похоже что ты не совсем правильно используешь форкджойн. Вроде проще от RecursiveAction наследоваться. Там invokeAll гарантированно дожидается результатов из подтасков.
Re[5]: Запись в массив double-ов из нескольких потоков
От: kuaw26 Россия  
Дата: 11.05.11 14:48
Оценка:
Здравствуйте, Nicht, Вы писали:

N>Ну судя по тому что он возвращает Future, то твой код не правильный потому что не вызывает у этих future get() и тем самым вообще не дожидается завершения выполнения.

N>После беглого просмотра документации похоже что ты не совсем правильно используешь форкджойн. Вроде проще от RecursiveAction наследоваться. Там invokeAll гарантированно дожидается результатов из подтасков.

Я в самом начале делал и через RecursiveAction. И делал просто через fixedThreadPool + CyclicBarrier. Всяко разно пробовал.
И уже сам не въезжаю почему сейчас у меня работает, а до этого какой-то бред был.
Насчет неправильности. в джава доке же сказано, что "when all complete" и у всех фьючеров будет "isDone() is true" на кой тогда еще get() делать?
Что бы гарантировать тот самый ордеринг?

Причем что интересно. Дебажил под клипсой.
Захожу в метод расчета. Происходит вычисление функции (все нормально, значение > 0).
Потом происходит присваивание в массив и клипс показывает, что как бы присваивания не произошло.... i-ый элемент массива так и остался со значением 0
или это не прозошол сброс данных в память?


сначала я смог побороть это поведение кодом вида:
syncronized(массив)
{
массив[i] = значение.
}
но это же бред так писать. я же типа ускорял расчеты.
потом я такой код убрал. и после 101 переписывания пока все работает,... а я ломаю голову
Re[2]: Запись в массив double-ов из нескольких потоков
От: KRA Украина  
Дата: 11.05.11 20:59
Оценка:
Здравствуйте, kuaw26, Вы писали:

K>У меня как раз ThreadPool. Как мне синхронизовать в ручную?


http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CyclicBarrier.html
Re[2]: Запись в массив double-ов из нескольких потоков
От: Donz Россия http://donz-ru.livejournal.com
Дата: 12.05.11 07:39
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Нагуглилась ссылка по теме. Про volatile вообще и массивы в частности.

B>http://jeremymanson.blogspot.com/2009/06/volatile-arrays-in-java.html

Полезно, но по сути ничего нового. Как у автора получилось после окончания записи при join вызове получить невалидные значения в основной нити, не объясняет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.