2016-03-10 4 views
2
private final ConcurrentHashMap<Float, VoteItem> datum = new ConcurrentHashMap<>(); 

public void vote(float graduation) { 
    datum.putIfAbsent(graduation, new VoteItem(graduation, new AtomicInteger(0))); 
    datum.get(graduation).getNum().incrementAndGet(); 
} 

Проголосовал ли метод за то, что он полностью потокобезопасен? VoteItem.getNum() возвращает AtomicInteger? Или, если есть лучший способ достичь этого?Реально ли это работает на ConcurrentHashMap?

ответ

4

Если VoteItem#getNum() является потокобезопасным, e. г. возвращает окончательное свойство, и. Никакие удаления не выполняются в параллельном потоке, ваш код также является потокобезопасным, так как нет возможности для putIfAbsent() для перезаписывания существующей записи и, следовательно, нет возможности для get() для возврата записи, которая будет перезаписана.

Но есть более простой способ добиться этого результата с использованием в putIfAbsent(), который возвращает существующую ценность, если она присутствует для данного ключа:

public void vote(float graduation) { 
    VoteItem i = datum.putIfAbsent(graduation, new VoteItem(graduation, new AtomicInteger(1))); 
    if (i != null) 
     i.getNum().incrementAndGet(); 
} 

Это обрабатывает возможность одновременно абсорбции, а также. В отличие от вашего кода, где одновременное удаление может выполняться между putIfAbsent() и get(), что вызывает NPE, здесь такой ситуации не может быть.

и рассмотреть возможность использования computeIfAbsent() вместо putIfAbsent() для того, чтобы избежать unnessessary VoteItem творения:

public void vote(float graduation) { 
    datum.computeIfAbsent(graduation, g -> new VoteItem(g, new AtomicInteger(0))) 
     .getNum() 
     .incrementAndGet(); 
} 

Вызов getNum() на результат возможен, потому что в отличие от putIfAbsent(), который возвращает нулевое значение, если значение не существовало до insertion, он возвращает только вычисленное значение.

+0

Привет, Саша. Могу ли я задать еще один вопрос: если после VoteItem выполните следующее редактирование xyz = datum.get (xx); на переменную xyz, делает ли она (xyz) потокобезопасной? –

+0

@YuSun это зависит от того, выполняется ли такое редактирование атомарно или нет (то есть, если есть вероятность, что другой поток увидит несогласованное состояние при выполнении редактирования или выполнит параллельные инварианты редактирования взлома). Трудно сказать, не видя кода –

+0

Я понял. Большое спасибо. –