I've been reading a section about volatile variable in the JSL. The spec provides an example and I tried to experiment with it. I've written the code:
static volatile int i = 0, j = 0;
public static void main(String args[]) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int k = 0; i < 200000; k++) {
i++;
j++;
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int k = 0; i < 200000; k++) {
System.out.println("i=" + i + " j=" + j);
}
}
});
t1.start();
t2.start();
}
Ok, I expected that j<=i
(spec said that), but it's not true:
i=147609 j=147684
i=149412 j=149521
i=150447 j=150523
i=151384 j=151457
i=152307 j=152380
i=153222 j=153297
i=154139 j=154214
i=155065 j=155138
i=155967 j=156040
i=156880 j=156952
i=157790 j=157863
i=158760 j=158833
i=159671 j=159747
i=160592 j=160664
i=161510 j=161584
i=162420 j=162497
i=163350 j=163425
i=164292 j=164365
i=165230 j=165306
i=166179 j=166252
i=167113 j=167187
i=168055 j=168128
i=169002 j=169078
i=169948 j=170021
i=170898 j=170974
i=171851 j=171924
i=172794 j=172866
i=173724 j=173796
i=174658 j=174733
i=175641 j=175714
i=176572 j=176645
i=177503 j=177575
i=178442 j=178517
i=179394 j=179467
i=180328 j=180403
i=181276 j=181351
i=182232 j=182305
i=183178 j=183251
i=184130 j=184205
i=185092 j=185167
i=186043 j=186118
i=186998 j=187071
i=195792 j=195866
i=196718 j=196784
i=197629 j=197698
i=198543 j=198608
i=199489 j=199555
What's wrong?
The actual value of i
will always be bigger or equal to j
.
What you are seeing in the logs is not the actual (current) value of i
and j
. It is the value of i
and j
at the moment they were evaluated.
Your linked document states
It is possible, however, that any given invocation of method two might observe a value for j that is much greater than the value observed for i, because method one might be executed many times between the moment when method two fetches the value of i and the moment when method two fetches the value of j.
Thread t1
runs, increments i
and j
a bunch of times. Context switch. Thread t2
runs, evaluates i
and concatenates it. Context switch. Thread t1
continues incrementing i
and j
. Context switch. Thread t2
evaluates j
and concatenates it. So j
is still smaller or equal to i
, you just evaluated them at different times.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments