This program does not terminate!
public class Main extends Thread {
private int i = 0;
private int getI() {return i; }
private void setI(int j) {i = j; }
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
main.start();
Thread.sleep(1000);
main.setI(10);
}
public void run() {
System.out.println("Awaiting...");
while (getI() == 0) ;
System.out.println("Done!");
}
}
I understand this happens because the CPU core running the Awaiting
loop always sees the cached copy of i
and misses the update.
I also understand that if I make volatile
private int i = 0;
then the while (getI()...
will behave[1] as if every time it is consulting the main memory - so it will see the updated value and my program will terminate.
My question is: If I make
synchronized private int getI() {return i; }
It surprisingly works!! The program terminates.
I understand that synchronized
is used in preventing two different threads from simultaneously entering a method - but here is only one thread that ever enters getI()
. So what sorcery is this?
Edit 1
This (synchronization) guarantees that changes to the state of the object are visible to all threads
So rather than directly having the private state field i
, I made following changes:
In place of I did private int i = 0;
private Data data = new Data();
, changed to i = j
data.i = j
and changed to return i
return data.i
Now the getI
and setI
methods are not doing anything to the state of the object in which they are defined (and may be synchronized). Even now using the synchronized
keyword is causing the program to terminate! The fun is in knowing that the object whose state is actually changing (Data
) has no synchronization or anything built into it. Then why?
[1] It will probably just behave as that, what actually, really happens is unclear to me