Java volatile array?

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

Ответ 1

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

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

Вы делаете это путем:

arr = arr; 

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

Ответ 2

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

Ответ 3

EDIT: массивы объектов в java. если вы сделаете ссылку на этот объект volatile, делает его видимым для других потоков, если вы обмениваете ссылку на массив. Однако это не выполняется для самих значений массива.

Получив лучшее отличие от модели java-памяти, на самом деле есть возможность обойти ее без Atomic * Array. Использование взаимозависимости для волатильных чтений и нормальной записи позволяет:

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

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

OLD: написание самоопределения arr=arr на самом деле не помогло бы.

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

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

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

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

Ответ 4

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

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;

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