Flying visibility guarantees, synchronization guarantees visibility and atomicity
Only guarantee this, if x or y updated by one thread, then the update will be visible to all threads. The order of execution depends only on how your threads work. The answer to the question of context switching is no, since the comparison occurs before input, so it will be only once, and it will be based on the value of the variable at that time. This is possible if you have several comparisons for the same variable.
The best way to use volatile is to maintain class state variables. Where in any new assignment will be displayed in all threads that refer to this class
If you look at the source code of ThreadPoolExecutor , some state variables will be unstable.
One of them is runState , which determines the state of ThreadPoolExecutor . Now when shutdown() is called runState , it is updated to SHUTDOWN , so the methods that accept the execute submit task stop accepting the task, which turns out to be simple if(runState==RUNNING)
Below is the execute code of the ThreadPoolExecutor method
In the code below, if you do not see any additional synchronization for poolSize , runState , since they are mutable state variables.
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); if (**poolSize** >= corePoolSize || !addIfUnderCorePoolSize(command)) {//poolSize volatile if (**runState** == RUNNING && workQueue.offer(command)) {//runstate volatile if (**runState** != RUNNING || **poolSize** == 0)//runstate volatile ensureQueuedTaskHandled(command); } else if (!addIfUnderMaximumPoolSize(command)) reject(command); // is shutdown or saturated } }
When not to use it?
If a variable is to be used in atomic operations or when one value of a variable depends on another value of the variable, for example. Increment i ++.
Alternative
Atomic variables are better called volatile , which have memory semantics as mutable, but provide you with additional operations. e.g. incrementAndGet () provided by AtomicInteger.