The problem here can be fixed by changing
static int i=0;
to
static volatile int i=0;
Creating a volatile variable has a number of complex consequences, and I am not an expert in this. So, I will try to explain how I think about it.
The variable i is in your main memory, your RAM. But RAM is slow, so your processor copies it to faster (and less) memory: cache. Lots of caches actually, but this is inappropriate.
But when two threads on two different processors put their values ββin different caches, what happens when the value changes? Well, if thread 1 changes the value in cache 1, thread 2 still uses the old value from cache 2. Unless we tell both threads that this variable i can change at any time, as if it were magic. This is the volatile keyword.
So why does it work with a print statement? Well, the print statement invokes a lot of code behind the scenes. Some of this code most likely contains a synchronized block or other mutable variable that (by chance) also updates the value of i in both caches. (Thanks to Marco13 for pointing this out).
The next time you try to access i , you will get an updated value!
PS: I say RAM here, but it's probably the closest shared memory between two threads, which could be a cache if they are, for example, hyper-threads.
This is also a great explanation (with pictures!):
http://tutorials.jenkov.com/java-concurrency/volatile.html
source share