By referring to http://www.javamex.com/tutorials/synchronization_volatile.shtml, I am not sure whether I need to use volatile
keyword in the following case, due to additional rule 3.
Will the new value written by Thread A, will always committed to main memory, after it "dead"? If yes, does it mean I need not volatile
keyword if the above 3 conditions are meet?
I am doubt that volatile
is being required in this case. As it is required, then ArrayList may broken. As one thread may perform insert and update size
member variable. Later, another thread (not-concurrently) may read the ArrayList
's size
. If you look at ArrayList
source code, size
is not being declared as volatile.
In JavaDoc of ArrayList
, then only mention that ArrayList
is not safe to be used for multiple threads access an ArrayList instance concurrently, but not for multiple threads access an ArrayList instance at different timing.
Let me use the following code to issulate this problem
public static void main(String[] args) throws InterruptedException {
// Create and start the thread
final ArrayList<String> list = new ArrayList<String>();
Thread writeThread = new Thread(new Runnable() {
public void run() {
list.add("hello");
}
});
writeThread.join();
Thread readThread = new Thread(new Runnable() {
public void run() {
// Does it guarantee that list.size will always return 1, as this list
// is manipulated by different thread?
// Take note that, within implementation of ArrayList, member
// variable size is not marked as volatile.
assert(1 == list.size());
}
});
readThread.join();
}
When To Use Volatile in C/C++ A variable should be declared volatile whenever its value could change unexpectedly. In practice, only three types of variables could change: Memory-mapped peripheral registers.
The volatile field is needed to make sure that multiple threads always see the newest value, even when the cache system or compiler optimizations are at work. Reading from a volatile variable always returns the latest written value from this variable.
If it is accessed only from synchronized blocks is not needed the volatile keyword. Synchronized guarantees that changes to variables accessed inside the synchronized block are visible to all threads entering a synchronized block.
Yes, you still need to use volatile (or some other form of synchronization).
The reason why is that the two threads could run on different processors and even if one thread has long finished before the other starts there is no guarantee that the second thread will get the freshest value when it makes the read. If the field is not marked as volatile and no other synchronization is used, then the second thread could get a value that was cached locally on the processor it is running on. That cached value could in theory be out-of-date for a long period of time, including after the first thread completed.
If you use volatile the value will always be written to and read from main memory, bypassing the processor's cached value.
No, you may not need it. despite Mark Byers answer begin fairly accurate, it is limited. synchronized and volatile are not the only ways to correctly pass data between threads. there are other, less talked about "synchronization points". specifically, thread start and thread end are synchronization points. however, the thread which is starting Thread B must have recognized that Thread A is finished (e.g. by joining the thread or checking the thread's state). if this is the case, the the variable does not need to be volatile.
Possibly yes, unless you manually create a memory barrier. If A sets the variable, and B decides to take oit from some registry, you have a problem. So, you need a mmemory barrier, either implicit (lock, volatile) or explicit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With