I have the following program:
class Resource {
static volatile int i = 0;
}
class MyThread extends Thread {
Resource resource;
String name;
public MyThread(Resource resource, String name ) {
this.resource = resource;
this.name = name;
}
@Override
public void run() {
int count = 1;
while(count <= 1000) {
if ("T1".equals(name)) {
if (count % 5 == 0) {
resource.i = count;
System.out.println(name + ", Resource's value = " + resource.i);
}
} else {
System.out.println(name + ", Resource's value = " + resource.i);
}
count++;
}
}
}
public class TestVolatile {
public static void main(String[] args) {
Resource resource = new Resource();
new MyThread(resource, "T1").start();
new MyThread(resource, "T2").start();
new MyThread(resource, "T3").start();
}
}
Based on some condition, I am setting the value of volatile variable by one thread named T1, expecting the value to be reflected in other two threads T2 and T3. I am doing an atomic operation, but I am getting unexpected output:
T2, Resource's value = 20
T2, Resource's value = 20
T2, Resource's value = 20
T2, Resource's value = 20
T2, Resource's value = 20
T1, Resource's value = 20
T1, Resource's value = 25
T1, Resource's value = 30
T1, Resource's value = 35
T3, Resource's value = 20
T3, Resource's value = 40
T3, Resource's value = 40
T3, Resource's value = 40
T3, Resource's value = 40
T1, Resource's value = 40
T3, Resource's value = 40
T1, Resource's value = 45
T1, Resource's value = 50
T1, Resource's value = 55
T1, Resource's value = 60
T3, Resource's value = 45
T3, Resource's value = 65
T3, Resource's value = 65
.
.
My understanding is once T1 sets the values into Resource's i, following it, printing Resource's i value under T2 and T3 should have been the same value set by T1. In output line 9, T1 = 35 but in line 10, T3 = 20. How come ? I am not doing any non atomic operation. Kindly let me know if I am missing out something. Thanks.
IMO, Your problem is here:
That is not an atomic operation. It must at least;
resource.i
,String
by copying the values ofname
and the given literal string and the decimal number previously computed,System.out.println
on the new string.It might do more than that (e.g., it might construct more than just one new object).
A lot can happen in between the moment when a calling thread fetches the value of
resource.i
and the moment when it finally enters asynchronized
statement somewhere within theSystem.out.println
call. For example, It's entirely believable that theT1
thread could callprintln
three times in between the moment when theT3
thread fetchesresource.i
(value equals 20), and the moment when theT3
thread finally callsprintln
with the string,"T3, Resource's value = 20"
.