So imagine the following situation:
Two threads with the same implementation running and you want both stop running if one of them inside your logic and conditions change an existing attribute boolean to false.
Easy. Just one of the threads I set the false value in the attribute. Is not it ?
No. It will not work because the second thread will never see this attribute with the value false, it will always look for the information on your local cache and it will be marked as true and no matter what you changed in main memory to false with the other thread. Thus the second thread will be running forever.
Why it happens?
If you are working with threads you need remember all threads which you implemented will be transforms in a natives threads by JVM machine. Threads, also has a local cache. In this case, then in the second thread the boolean type attribute in your local cache is still marked as true.
How then do the thread does not get the cached value? How to thread fetch the value in main memory?
You need to tell it to the JVM. You need to disable caching of this attribute, for always the thread look the current value of it. For do this, we need define this attribute as Volatile.
public volatile boolean myValue;
Is this the best way to do it?
After the release of Java 1.5 we have a new type of object implemented in the package:
java.util.concurrent
See below:
AtomicBoolean
So, we can implement this as follows:
private AtomicBoolean myValue;
What is the difference between volatile and AtomicBoolean?
In fact AtomicBoolean is an abstraction of this logic which will use the volatile type attribute. See the implementation of this class below:
Why use AtomicBoolean then?
The advantage is that this type of object allows more features and makes it clearer in time to view the code. This object has methods that can help you to perform other operations.
Is there any other alternative to solve this problem?
As we have seen this is a clear problem of synchronization, instead of using the value of main memory the thread uses the value it finds in your local cache. We can force the synchronization of these attributes defining the methods as:
synchronized
In this way, we are telling the JVM synchronize attributes in this method before using the value, so then it must update the value of the attribute with the value in the main memory before using it.
In the tutorial Oracle is presented as a small example would be a class using synchronized compared with AtomInteger. It is worth checking:
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomicvars.html
Above we talked about the AtomicBoolean not need to synchronize access to a variable. The class is part of the package java.util.concurrent.atomic where we can find other classes, such as AtomicInteger and AtomicLong.
You can check the documentation of the oracle:
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html