Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Atomically update multiple volatile and j.u.c.atomic variables

In order to atomically update two and more volatile variables does it need to be guarded by lock with synchronized, reentrantReadWriteLock etc?

i.e.

volatile int vVar1, vVar1; // or AtomicInteger

/*** Needs to be updated atomically ***/
void atomicUpdate(int var1, int var2){
  vVar1 = var1;
  vVar2 = var2;
}

The same code is for java.util.concurrent.atomic variables.

like image 449
Sayat Satybald Avatar asked Dec 26 '22 00:12

Sayat Satybald


2 Answers

If you need to assign two values atomically, chaning volatile int to AtomicInteger will not solve your race condition problem.

To solve your issue, you basically have two options:

  1. Make the methods updating the variables synchronized (and maybe the methods reading those variables too)
  2. Create an wrapper for your two variables, and make use of the fact that assignment is an atomic operation

Example for option 2:

volatile Vars vars;
void atomicUpdate(int var1, int var2) {
    vars = new Vars(var1, var2);
}

public static Vars {
    private int vVar1;  // volatile if they need to be modified
    private int vVar2;
}

I largely prefer option 2 since it is non blocking and allows you to cache any type of data.

like image 54
Jean Logeart Avatar answered Dec 27 '22 13:12

Jean Logeart


Create a Class which encapsulates all of your state variables, then use AtomicReference to refer to them. This alleviates race conditions where a thread needs to set/check multiple values safely.

// set initial state
AtomicReference<MyState> ref = new AtomicReference<MyState>();
ref.set(new MyState("abc", "def"));

// .. Thread 1 needs to change the state:
ref.set(new MyState("xyz", "def"));

// .. Thread 2 needs to read the state (consistently):
MyState state = ref.get();
if ("test1".equals(state.a)) { }
else if ("test2".equals(state.b) { }

The benefit here is that Thread 2 is able to read MyState.a and MyState.b consistently from the same MyState instance, as opposed to having the MyState instance variable it's referencing change in-between checks.

like image 30
Alex Avatar answered Dec 27 '22 14:12

Alex