#java #arrays #synchronized
#java #массивы #синхронизировано
Вопрос:
Если я хочу заблокировать весь массив, я могу использовать synchronized
ключевое слово следующим образом:
int arr[];
synchronized void inc(int a, int b){
arr[a]=arr[a] b;
}
Но могу ли я заблокировать только элемент arr[a]
, чтобы другие потоки могли одновременно читать / записывать другие элементы массива?
Ответ №1:
Может быть, более подходящая структура для вас AtomicIntegerArray
Комментарии:
1. Это, вероятно, лучший ответ, однако ответ Рэя — это решение, которое я искал для своего конкретного случая
Ответ №2:
Не готовый, но вы можете создать массив объектов того же размера, что и ваш массив int, и заполнить массив различными объектами. Поэтому, когда вы хотите заблокировать определенный элемент в массиве int, вы блокируете этот объект по соответствующему индексу:
final Object[] locks = new Object[arr.length]:
for(int i = 0; i < arr.length; i ) {
locks[i] = new Object();
}
При блокировке: выполните
synchronized(locks[a]) {
// do something here
}
Ответ №3:
Нет, элементы массива являются примитивами, и вы не можете их заблокировать. (Это также не помогло бы, если бы они были объектами, потому что блокировка помогает только для изменяемых объектов. Вы хотите заблокировать индекс массива, а не содержимое по этому индексу).
Единственная возможная конструкция, которая приходит на ум, — это создать ключ, который однозначно ссылается на индекс массива, и синхронизировать его (или использовать a Semaphore
), но это поможет только в том случае, если другой поток обращается к массиву таким же образом.
Я бы сказал, что хорошей отправной точкой было бы изменить ваш дизайн, избавиться от массива int и использовать структуру данных, которая позволяет синхронизировать доступ к его элементам ( List
завернутый с Collections.synchronizedList()
).
Ответ №4:
Если для вас это действительно бутылочное горлышко, скорее всего, более подходящей будет совершенно другая структура. Если у вас, скажем, 8 ядер, то они должны быть заняты и тратить около 1/8 времени на добавление чисел, чтобы увидеть серьезную конкуренцию. Если выполнение этих операций составляет около 1/8 вашей работы, вы должны спроектировать свою систему так, чтобы она вообще не блокировала это.
Допустим, вам нужно получить общее количество значений в нескольких потоках. например, подсчитать количество случаев, когда число отображается в очень длинном списке.
У вас может быть один синхронизированный массив счетчиков с очень дорогой блокировкой при каждом обновлении. (Синхронизация выполняется быстро, но намного, намного медленнее, чем добавление)
Или вы могли бы заставить все потоки сохранять свои собственные итоги, которые вы суммируете в конце. Итоговый результат тот же, за исключением того, что вы не использовали никаких блокировок!