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.
You can't. There are no atomic operations in the Java language or in the Java standard library that span more than one variable.
You can probably solve your problem using the
synchronized
keyword, but usingsynchronized
is different from using atomics because, in order for it to work, the threads must cooperate with one another.If there is a specific relationship that must always exist between those two variables (a.k.a., an invariant), and if you can't update the variables without temporarily breaking the invariant, then you must synchronize the code that does the update, and you must also synchronize every other block of code that expects the invariant to be true.
That's because, when you write this:
It doesn't prevent other threads from doing anything except synchronizing on the same object at the same time.
Also note: Once you have properly synchronized all access to the variables, then you won't need them to be
volatile
. That's because whatever one thread writes to memory before releasing a lock is guaranteed to become visible to any other thread that subsequently acquires the same lock.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.
The benefit here is that
Thread 2
is able to readMyState.a
andMyState.b
consistently from the sameMyState
instance, as opposed to having theMyState
instance variable it's referencing change in-between checks.An alternative would be to use a volatile array:
that would be atomic but it assumes that the rest of your code does not access vVar1 and vVar2 directly. There may be better options depending on what you are trying to achieve - for example you could create an ad hoc thread safe holder class (typically immutable) for the two ints.
If you need to assign two values atomically, chaning
volatile int
toAtomicInteger
will not solve your race condition problem.To solve your issue, you basically have two options:
synchronized
(and maybe the methods reading those variables too)Example for option 2:
I largely prefer option 2 since it is non blocking and allows you to cache any type of data.