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[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[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
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.