Java энергозависимый массив? - PullRequest
16 голосов
/ 03 марта 2011

Как сделать массив изменчивым? Потому что, как я понял, опасно делать массив изменчивым?

Ответы [ 4 ]

17 голосов
/ 03 марта 2011

Объявление массива volatile не дает волатильный доступ к его полям.Вы объявляете саму ссылку volatile, а не ее элементы.

Другими словами, вы объявляете volatile набор элементов, а не набор volatile элементов ,Решение здесь состоит в том, чтобы использовать AtomicIntegerArray в случае, если вы хотите использовать целые числа.

Другой способ (но довольно уродливый) - переписывать ссылку на массив каждый раз, когда вы редактируете поле.

Вы делаете это с помощью:

arr = arr; 

(как я сказал ... некрасиво)

7 голосов
/ 03 марта 2011

AtomicLongArray, AtomicIntegerArray, AtomicReferenceArray (java.util.concurrent.atomic).

3 голосов
/ 23 августа 2017

РЕДАКТИРОВАТЬ: массив объектов в Java.если вы сделаете ссылку на этот объект энергозависимой, она станет видимой для других потоков, если вы обменяетесь ссылкой на массив.Однако это не относится к самим значениям массива.

Чтобы лучше понять модель памяти Java, существует возможность обойти ее без массива Atomic *.Использование отношения «произошло до» для энергозависимых чтений и обычных записей делает возможным:

, если поток A записывает некоторые энергонезависимые данные, а переменная после , что поток B гарантированно увидитизменения в энергозависимом материале, но только в том случае, если поток B сначала читает переменную.см. также: Связи до появления с энергозависимыми полями и синхронизированными блоками в Java - и их влияние на энергонезависимые переменные?

Для массивов это означает: после записи в массив,запись в некоторую переменную состояния volatile (убедитесь, что запись действительно изменяет переменную состояния volatile!) Когда вы читаете из массива, сначала прочитайте переменную состояния volatile, а затем получите доступ к массиву.В результате энергозависимого чтения все остальные записи также будут видны, если они произошли раньше.

СТАРЫЙ: запись собственной ссылки arr=arr на самом деле не поможет.

Вы пишете адресмассива arr, а не значение поля arr[i].Таким образом, вы по-прежнему не получаете летучих свойств для arr[i] (которые вы хотите), а только для адреса хранения arr.

Ранее упомянутый пост блога Джереми Мэнсона объясняет это подробно: http://jeremymanson.blogspot.com/2009/06/volatile-arrays-in-java.html

Его лучшее решение - использовать массивы Atomic *, а именно AtomicReferenceArray для универсальных типов (также существуют специальные формы дляосновные типы).Я не могу себе представить, что это особенно эффективно, тем более что оно дает вам больше необходимых вам свойств (атомарность >> volatile).

Альтернативой могут быть указательные структуры, в которых контейнеры используют изменяемые поля указателя.Тоже не так эффективно ...

1 голос
/ 06 марта 2019

Как насчет этого:

static class Cell<T> {
        volatile T elem;
    }

private Cell<T>[] alloc(int size){
        Cell<T>[] cells = (Cell<T>[]) (new Cell[size]);
        return cells;
    }

 volatile Cell<T>[] arr;
 Cell<T>[] newarr = alloc(16);
 for (int i = 0; i < newarr.length; i++) {
      newarr[i] = new Cell<>();
 }
 arr = newarr;

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

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