Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I need to use volatile, if 2 different write and read thread will never alive at the same time

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.

  1. A primitive static variable will be write by Thread A.
  2. The same primitive static variable will be read by Thread B.
  3. Thread B will only run, after Thread A is "dead". ("dead" means, the last statement of Thread A's void run is finished)

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();
}
like image 285
Cheok Yan Cheng Avatar asked Jan 23 '11 15:01

Cheok Yan Cheng


People also ask

When should volatile be used?

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.

Will we need volatile if we had no caches?

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.

Is volatile required with synchronized?

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.


3 Answers

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.

like image 51
Mark Byers Avatar answered Oct 06 '22 01:10

Mark Byers


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.

like image 45
jtahlborn Avatar answered Oct 05 '22 23:10

jtahlborn


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.

like image 21
TomTom Avatar answered Oct 06 '22 00:10

TomTom