My Code is
package threadrelated;
import threadrelated.lockrelated.MyNonBlockingQueue;
public class VolatileTester extends Thread {
MyNonBlockingQueue mbq ;
public static void main(String[] args) throws InterruptedException {
VolatileTester vt = new VolatileTester();
vt.mbq = new MyNonBlockingQueue(10);
System.out.println(Thread.currentThread().getName()+" "+vt.mbq);
Thread t1 = new Thread(vt,"First");
Thread t2 = new Thread(vt,"Secondz");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(Thread.currentThread().getName()+" "+vt.mbq);
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" before "+mbq);
mbq = new MyNonBlockingQueue(20);
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" after "+mbq);
}
}
Output is
main threadrelated.lockrelated.MyNonBlockingQueue@72fcb1f4
Secondz before threadrelated.lockrelated.MyNonBlockingQueue@72fcb1f4
First before threadrelated.lockrelated.MyNonBlockingQueue@72fcb1f4
Secondz after threadrelated.lockrelated.MyNonBlockingQueue@7100650c
First after threadrelated.lockrelated.MyNonBlockingQueue@7100650c
main threadrelated.lockrelated.MyNonBlockingQueue@7100650c
It shows that when First thread assigns member variable to new object, same is visible to other thread. Even if "mbq" is not declared as volatile.
I used breakpoints to try different sequence of operations. But my observation is that one thread can immediately see impact of other thread.
Is volatile not needed for class members which are object ? Are they always synchronized to main memory ? Volatile needed only for primitive member variables (int, long, boolean etc. ? )
It's just as necessary for references as it is for primitives. The fact that your output doesn't show a visibility problem doesn't prove one doesn't exist. In general, it's very difficult to prove non-existence of a concurrency bug. But here's a simple counterproof showing the necessity of volatile
:
public class Test {
static volatile Object ref;
public static void main(String[] args) {
// spin until ref is updated
new Thread(() -> {
while (ref == null);
System.out.println("done");
}).start();
// wait a second, then update ref
new Thread(() -> {
try { Thread.sleep(1000); } catch (Exception e) {}
ref = new Object();
}).start();
}
}
This program runs for a second, then prints "done". Remove volatile
and it won't terminate because the first thread never sees the updated ref
value. (Disclaimer: As with any concurrency test, results may vary.)