Нужна ли синхронизация при манипулировании различными индексами массива (массива объектов) - PullRequest
2 голосов
/ 02 июня 2009

В контексте Java, у меня есть такой код,

MyObject[] array;

и в разных темах у меня есть такой код

array[i] = new MyObject(val);

Если я гарантирую, что каждый из моих потоков использует разные значения "i", тогда мне нужно будет синхронизировать вышеупомянутое выражение, чтобы позаботиться о состоянии гонки?

Ответы [ 4 ]

3 голосов
/ 02 июня 2009

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

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

3 голосов
/ 02 июня 2009

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

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

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

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

2 голосов
/ 02 июня 2009

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

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

0 голосов
/ 04 июня 2009

Здесь три дискретных объекта с синхронизацией.

Сама переменная массива: Объявление переменной array как volatile или final (или синхронизация по array) имеет важное значение, так что оба потока гарантированно получают доступ к одному и тому же экземпляру массива , Если нет, возможно следующее:

  1. Потоки A и B запускаются
  2. Thread A создает array как новый объект Array
  3. Поток B пытается получить доступ к потоку A array, но получает NullPointerExceptoin потому что он еще не видит назначение потоком A нового массива array.

Не хорошо.

Массив ссылается на экземпляры MyObject (и, как представляется, актуальный вопрос Венкатрамана): Если переменная array сама синхронизирована должным образом, то yes, два потока могут обращаться к различным элементам в массив надежно. Как только дочерний поток завершит делать то, что делал, тогда «главный» поток захочет синхронизировать массив, чтобы убедиться, что он получает конечное состояние дочерних элементов массива перед их использованием.

Сами экземпляры MyObject , но это выходит за рамки вопроса

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...