Доступ к массиву от нескольких потоков

Скажем, у меня есть два массива:

int[] array1 = new int[2000000];
int[] array2 = new int[2000000];

Я засовываю некоторые значения в массивы и затем хочу добавить содержание array2 к array1 как так:

for(int i = 0; i < 2000000; ++i) array1[i] += array2[i];

Теперь, скажем, я хочу сделать обработку быстрее на многопроцессорной машине, таким образом, вместо того, чтобы просто делать цикл как вышеупомянутый, я создаю два потока. Один из которых я имею, обрабатывают первые 1 000 000 элементов в массиве, другой я имею, обрабатывают последние 1 000 000 элементов в массиве. Мой основной поток ожидает тех двух потоков, чтобы уведомить его, что они закончены, и затем продолжает использовать значения от array1 для всех видов важного материала. (Обратите внимание, что эти два рабочих потока не могут быть завершены и могут быть снова использованы, но основной поток не возобновится, пока они оба не уведомили его, чтобы сделать так.)

Так, мой вопрос: Как я могу быть уверен, что основной поток будет видеть модификации, которые эти два рабочих потока сделали к массиву? Я могу рассчитывать на это для случая, или сделать я должен пройти некоторую специальную процедуру, чтобы удостовериться, что рабочие потоки сбрасывают свои записи к массиву, и основной поток отбрасывает свои значения кэшированного массива?

5
задан nonoitall 19 February 2010 в 00:59
поделиться

6 ответов

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

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

Если вам нужен явный барьер, используйте Thread.MemoryBarrier.

2
ответ дан 13 December 2019 в 19:26
поделиться

Если вам повезет и у вас есть возможность использовать .NET 4.0, вы можете просто написать:

Parallel.For(0, 2000000, i => { array1[i] += array2[i]; });

Вам не нужна явная блокировка или синхронизация, потому что:

  • Каждая задача (выполнение тела цикла for ) влияет на непересекающуюся часть массива
  • Parallel.For ожидает завершения всех задач, прежде чем вернуться, поэтому будет быть неявным барьером памяти.
6
ответ дан 13 December 2019 в 19:26
поделиться

Как я могу быть уверен, что основной поток увидит изменения, внесенные двумя рабочими потоками в массив? Могу ли я рассчитывать на то, что это произойдет, или мне нужно пройти специальную процедуру, чтобы убедиться, что рабочие потоки сбрасывают свои записи в массив, а основной поток отбрасывает свои кэшированные значения массива?

Вам не нужна особая обработка здесь - вы всегда будете работать с одними и теми же объектами в памяти.

Кроме того, поскольку каждый поток будет работать с отдельной частью массива, блокировка не требуется.

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

2
ответ дан 13 December 2019 в 19:26
поделиться

Вероятно, все будет в порядке, если вы используете обратные вызовы, когда они закончат изменять массивы, но если возникнут вопросы, использование блокировки позволит убедиться, что другие потоки отпустили массивы.

lock (array1)
{
}

http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.71).aspx

0
ответ дан 13 December 2019 в 19:26
поделиться

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

0
ответ дан 13 December 2019 в 19:26
поделиться

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

1
ответ дан 13 December 2019 в 19:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: