java - Possible to create AtomicReference that can be swapped atomically? -


is there way implement type of reference value can exchanged atomically?


in java have atomicreference can swapped local variable not atomicreference.

you can do:

atomicreference r1 = new atomicreference("hello"); atomicreference r2 = new atomicreference("world"); 

and swap them combination of 2 operations:

r1.set(r2.getandset(r1.get())); 

but leaves them in inconsistent state in between, both contain "hello". if swap them atomically, still not read them (as pair) atomically.


what able is:

pairableatomicreference r1 = new pairableatomicreference("hello"); pairableatomicreference r2 = new pairableatomicreference("world"); atomicrefpair rp = new atomicrefpair(r1, r2); 

then

object[] oldval, newval; {     oldval = rp.get();     newval = new object[] {oldval[1], oldval[0]}; } while (! rp.compareandset(oldval, newval)); 

to swap values, , in thread:

atomicrefpair otherrp = new atomicrefpair(r1, r2); system.out.println(arrays.tostring(otherrp.get())); 

and output either [hello, world] or [world, hello].

notes:

  • r1 , r2 paired operation, it's possible thread independently pair, r1 , r3 (unfortunately means cannot use this solution.)
  • there hundreds of thousands of these references, global reentrantlock major bottleneck.
  • rp , otherrp not shared between threads, locking them not work. interned, intern pool need own synchronization bottleneck.
  • i have made groups of 2 references here, ability group 3 or more bonus.

is possible implement lock-free version of atomicrefpair? have hunch isn't, if not maybe there article somewhere explains why?


related: how atomically swap 2 ints in c#?

i don't know if there's nice solution, following ugly 1 work:

public final class myreference<t> extends reentrantlock implements comparable<myreference<t>> {     public myreference() {         id = counter.incrementandget();     }      public void swap(myreference<t> other) {         if (id < other.id) {             lock();             other.lock();         } else {             other.lock();             lock();         }         final t tmp = value;         value = other.value;         other.value = tmp;         unlock();         other.unlock();     }      public static <t> list<t> consistentget(list<myreference<t>> references) {         final arraylist<myreference<t>> sortedreferences = lists.newarraylist(references);         collections.sort(sortedreferences);         (val r : sortedreferences) r.lock();         final list<t> result = lists.newarraylistwithexpectedsize(sortedreferences.size());         (val r : references) result.add(r.value);         (val r : sortedreferences) r.unlock();         return result;     }      @override     public int compareto(myreference<t> o) {         return id < o.id ? -1 : id > o.id ? 1 : 0;     }      private final static atomicinteger counter = new atomicinteger();      private t value;     private final int id; } 
  • use myreference instead of atomicreference.
  • it uses lot of locks, none of them global.
  • it acquires locks in fixed order, it's deadlock-free.
  • it compiles using lombok , guava (take pseudocode without them).

Comments

Popular posts from this blog

java - SNMP4J General Variable Binding Error -

windows - Python Service Installation - "Could not find PythonClass entry" -

Determine if a XmlNode is empty or null in C#? -