unsafe.compareAndSwapObject заменяет массив, который повторяется в другом потоке - PullRequest
0 голосов
/ 26 октября 2019

Я пытаюсь реализовать логику, которая позволит мне обновлять массив в одном потоке с помощью утилиты unsafe.compareAndSwapObject от Sun, одновременно безопасно перебирая этот же массив в другом потоке. Я полагаю, что CopyOnWriteArrayList делает то, что я ищу, однако он использует блокировку для обновления, и я пытаюсь разработать решение, которое не имеет каких-либо блокировок.

Логика сравнения и свопинга выглядит следующим образом:

public void add(final Object toAdd) {
    Object[] currentObjects;
    Object[] newObjects;
    do {
        currentObjects = this.objects;
        newObjects = ArrayUtil.add(currentObjects, toAdd);
    } while (!UNSAFE.compareAndSwapObject(this, OBJECTS_OFFSET, currentObjects, newObjects));
}

Хотя логика итерации следующая (toString () является заполнителем):

public void doWork() {
    Object[] currentObjects = this.objects;
    for (final Object object : currentObjects) {
        object.toString();
    }
}

Мои вопросы:

  1. Безопасен ли этот код?
  2. Дает ли это мне такое же поведение моментального снимка, как CopyOnWriteArrayList?
  3. Если да, когда формируется моментальный снимок итерации?
    • Имеет ли факт, что я создаю локальную переменную, что-нибудь для этого?
    • Если да, как JVM узнает, что это не оптимизировать?
    • По сути, я создал переменную в стеке, которая имеет ссылку на самый актуальный объект массива?

И наконец, следуя третьему пункту выше о создании «снимка», следующий код будет работать так же:

public void doWork() {
    actuallyDoWork(this.objects);
}

public void actuallyDoWork() {
    for (final Object object : currentObjects) {
        object.toString();
    }
}
...