Поле Vavr Set должно быть изменчивым, атомарным или объявленным другим способом? - PullRequest
2 голосов
/ 20 мая 2019

В vavr у вас есть набор io.vavr.collection.Set, который является неизменным. Какой правильный и идиоматический способ использовать это, учитывая, что addName() и names() можно вызывать из разных потоков?

import io.vavr.collection.Set;
import io.vavr.collection.HashSet;
public class Names{
  public/*private*/ /**volatile*/ Set<String> names = HashSet.empty();
  public void addName(String name){
    names = names.add(name);
  }
  public Set<String> names(){
    return names;
  }
}

Должен ли я использовать летучие? Должен ли я использовать AtomicRef<Set<String>> вместо?

1 Ответ

1 голос
/ 21 мая 2019

Я бы использовал AtomicReference. Смотрите мой ответ на аналогичный вопрос. Volatile определенно не достаточно, потому что он только гарантирует, что обновления переменной будут видны другим потокам немедленно (это эффективно отключает кешированный доступ к ней). Однако одновременный доступ к потокам не будет синхронизирован, поэтому может случиться так, что два потока одновременно создадут обновленный Set, и один из потоков перезапишет изменение других потоков.

Учитывая два потока T1 и T2, которые работают одновременно, представьте следующую последовательность событий:

  1. T1 читает переменную, текущее состояние V
  2. T2 читает переменную, текущее состояние V
  3. T1 вычисляет обновленное состояние V × U1
  4. T2 вычисляет обновленное состояние V × U2
  5. T1 обновляет переменную до V × U1
  6. T2 обновляет переменную до V × U2

Конечное значение из вышеприведенной последовательности будет V × U2, поэтому обновление U1 фактически потеряно.

AtomicReference, с другой стороны, гарантирует, что переменная обновляется атомарно. Вам нужно будет передать функцию обновления в AtomicReference, чтобы она вызывалась до атомарного сохранения результата. Убедитесь, что вы используете чистую функцию без побочных эффектов, так как функция обновления может вызываться несколько раз в случае, если в это время ссылка была обновлена ​​атомным способом другим потоком.

...