I60R
I60R

Reputation: 487

How to "'validate and lazy swap' atomically" like CAS?

Here is prototype of function I want:

atomicReference.validateAndSwap(value -> isInvalid(value), () -> createValid());

It assumed to be called from multiple threads.
Second lambda is called only when first returns true.
First (plus second if first returns true) lambda calls should be a single atomic operation.

It is even possible to implement without synchronized?
Are there ready solutions for similar functionality?
Have I wrong way of thinking and miss something?

Upvotes: 2

Views: 133

Answers (1)

Holger
Holger

Reputation: 298579

I’m not sure whether you mean the right thing when saying “First (plus second if first returns true) lambda calls should be a single atomic operation.” The point of atomic references is that the update function evaluation may overlap and therefore, should not have interference, but will act as if being atomic, as when evaluations overlap, only one can succeed with CAS and the other has to be repeated based on the new value.

If you want truly atomic evaluations, using a Lock or synchronized is unavoidable. If you have appropriate non-interfering functions and want implement updates as if atomic, it can be implemented like

Value old;
do old = atomicReference.get();
   while(isInvalid(old) && !atomicReference.compareAndSet(old, createValid()));

Since in this specific case, the createValid() function does not depend on the old value, we could avoid repeated evaluation in the contended case:

Value old = atomicReference.get();
if(isInvalid(old)) {
  Value newValue = createValid();
  while(!atomicReference.compareAndSet(old, newValue)) {
    old=atomicReference.get();
    if(!isInvalid(old)) break;
  }
}

That all assuming that the validity of an object cannot change in-between. Otherwise, locking or synchronizing is unavoidable.

Note that the Java 8’s update methods follow the same principle. So you can write

atomicReference.updateAndGet(old -> isInvalid(old)? createValid(): old);

to achieve the same, but it also isn’t truly atomic but rather behaves as-if atomic if concurrent evaluations of the update function have no interference.

Upvotes: 1

Related Questions