Y a-t-il un moyen d'implémenter un type de référence dont la valeur peut être échangée avec une autre atomiquement?Possible de créer AtomicReference qui peut être permuté atomiquement?
En Java, nous avons AtomicReference
qui peut être échangé avec une variable locale, mais pas avec un autre AtomicReference
.
Vous pouvez faire:
AtomicReference r1 = new AtomicReference("hello");
AtomicReference r2 = new AtomicReference("world");
et de les échanger avec une combinaison de deux opérations:
r1.set(r2.getAndSet(r1.get()));
Mais ce qui les laisse dans un état incohérent entre, où les deux contiennent "hello"
. Même si vous pouviez les échanger atomiquement, vous ne pouviez toujours pas les lire (en paire) de façon atomique.
Ce que je voudrais être en mesure de faire est:
PairableAtomicReference r1 = new PairableAtomicReference("hello");
PairableAtomicReference r2 = new PairableAtomicReference("world");
AtomicRefPair rp = new AtomicRefPair(r1, r2);
puis
Object[] oldVal, newVal;
do {
oldVal = rp.get();
newVal = new Object[] {oldVal[1], oldVal[0]};
} while (! rp.compareAndSet(oldVal, newVal));
pour échanger les valeurs, et dans un autre thread:
AtomicRefPair otherRP = new AtomicRefPair(r1, r2);
System.out.println(Arrays.toString(otherRP.get()));
et soyez certain que la sortie sera soit [hello, world]
ou [world, hello]
.
Notes:
r1
etr2
sont appairés pour cette opération, mais il est possible qu'un autre thread indépendamment paire, disentr1
et un autrer3
- Il (malheureusement, cela signifie que je ne peux pas utiliser this solution.) sera des centaines de milliers de ces références, donc un
ReentrantLock
serait un goulot d'étranglement majeur. rp
etotherRP
ne sont pas nécessairement partagés entre les threads, donc simplement les verrouiller ne fonctionnera pas. Ils pourraient être interned, mais le pool interne aurait besoin de sa propre synchronisation, ce qui serait un autre goulot d'étranglement.- J'ai seulement fait des groupes de 2 références ici, mais la possibilité de grouper 3 ou plus serait un bonus.
Est-il possible d'implémenter une version sans verrou de AtomicRefPair
? J'ai l'intuition que ce n'est pas le cas, mais sinon, peut-être qu'il y a un article quelque part qui explique pourquoi?
connexes: How do I atomically swap 2 ints in C#?
Il y a un interneur dans Guava, qui utilise ConcurrentHashMap, donc la contention peut être arbitrairement petite en moyenne. – maaartinus