Я попытался реализовать метод swap для 2 AtomicReferences.Swap 2 значения в 2 разных AtomicReferences
public void swap(AtomicReference<Object> a, AtomicReference<Object> b) {
while (true) {
Object value1 = a.get();
Object value2 = b.get();
if (a.compareAndSet(value1, value2) && b.compareAndSet(value2, value1)) return;
}
}
На мой взгляд, это решение является неправильным. Если несколько потоков используют этот метод в то же время, это может привести к следующему сценарию:
T1: ...get(); get(); compareAndSet() == true //-> BREAK (scheduler)
T2: ...get(); get(); compareAndSet() == true; compareAndSet() == true; return;
Это будет означать, что T1 установить значение a
но потерпит неудачу, установив значение Ь. T1 будет повторять процесс EVEN, если установлен AtomicReference a.
У кого-то из вас есть лучшая идея, как реализовать что-то подобное? Было бы легко, если бы у вас был только один AtomicReference. Возможно, это невозможно, используя 2 AtomicReference, и я должен рассмотреть возможность использования одного AtomicReference, который указывает на Object [].
В Scala этот метод очень прост в реализации, поскольку у вас есть атомные блоки.
class Swappy[A](_a: A, _b: A) {
@volatile
var a = Ref(_a)
@volatile
var b = Ref(_b)
def swap(): Unit = {
atomic {
implicit tx =>
val tmp = a
a = b
b = tmp
}
}
def elems: (A, A) = (a.single(), b.single())
}
Не знаю Scala, но я, откровенно говоря, не вижу, как это может работать в принципе, если Scala не обманывает атомарные команды низкоуровневого процессора в свои собственные вещи. – doublep
На самом деле это не «настоящий» низкоуровневый атомный материал. Но он проверяет себя в конце блока, если все по-прежнему корректно (измененные значения не изменяются). Если нет, он откатится и начнет с начала атомного блока. :) – codepleb
Возможный дубликат [Java Atomicity & good Compare и Swap framework?] (Http://stackoverflow.com/questions/14771174/java-atomicity-a-good-compare-and-swap-framework) – rbp