Синхронизация Java-массивов - PullRequest
3 голосов
/ 20 февраля 2011

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

public static int[][][] tasks;

В основном я получаю доступ к таким клеткам:

synchronized(tasks[A][B]) {
  // Doing something with tasks[A][B][0]
}

Мой вопрос, если я сделаю это:

synchronized(tasks[A]) {
  // ...
}

также заблокирует ли потоки, пытающиеся войти в синхронизированный режим (задачи [A] [B])? Другими словами, синхронизированный доступ к массиву также синхронизирует доступ к его ячейкам? Если нет, то как заблокировать ВЕСЬ массив задач [A] для моего потока?


Изменить: ответ НЕТ. Когда кто-то находится в синхронизированном блоке для задач [A], кто-то другой может одновременно находиться в синхронизированном блоке, например, на задачах [A] [B] - потому что это другой объект. Поэтому, когда речь идет о доступе к объектам из одного места за раз, массивы ничем не отличаются: чтобы коснуться объекта X из одного места за раз, вам нужно окружить его синхронизированным (X) ВСЕГДА, где вы касаетесь его.

Ответы [ 3 ]

4 голосов
/ 20 февраля 2011

Нет.Каждый массив является объектом (с монитором) сам по себе;и массив tasks[A] является отличным от массива tasks[A][B] объектом.Решение, если вы хотите синхронизировать все обращения к «sub» массивам tasks[A], состоит в том, что вы просто должны сделать synchronized (tasks[A]).Если все обращения к объектам-потомкам (скажем, tasks[A][B]) делают это, то любая дальнейшая синхронизация является излишней.безопасно изменить структуру , а также содержимое структуры данных, сохранив при этом наилучший возможный параллелизм? "Если вы добавите свой вопрос немного больше о проблемном пространстве, мы могли бы углубиться.Трехмерный массив может быть не лучшим решением.

2 голосов
/ 20 февраля 2011

int [] [] [] - это массив массивов целочисленных массивов, поэтому ваша синхронизированная (tasks [A] [B]) синхронизируется на объекте самого низкого уровня, массиве целых чисел, блокируя другой синхронизированный доступ к этому тот же массив.

synchronized (tasks [A]), с другой стороны, синхронизирует объект на следующем уровне вверх - массив целочисленных массивов. Это предотвращает синхронизированный доступ к этому массиву, что означает, что на практике любой другой код, использующий синхронизированный (задания [A]), будет заблокирован - что, по-видимому, является тем, что вы хотите, при условии, что все ваши обращения к задачам синхронизируются одновременно уровень.

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

Неважно, что вы затем работаете с другим объектом (вашим массивом целых чисел).

Боюсь, я говорю, что ответ Андерсоя вводит в заблуждение. Вы делаете правильные вещи.

1 голос
/ 20 февраля 2011

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

Возможно, вам поможет объяснить, что вы пытаетесь выполнить и как вы используете / модифицируете этот массив tasks. Есть удивительное (или, возможно, неудивительное) количество случаев, когда утилиты в java.util.concurrent достаточны, и использование отдельных мониторов не является необходимым. Конечно, все зависит от того, что именно вы пытаетесь сделать. Кроме того, если причина, по которой вы пытаетесь захватить так много разных блокировок, заключается в том, что вы читаете их очень часто, возможно, что использование одной блокировки чтения-записи для всего объекта 3d с зубчатыми массивами может оказаться достаточным для ваших нужд.

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