Reputation: 21
Why the pool
does not set to 5 in the f()
method that is called by another thread?
public class Main {
private static int pool = 5;
public static void main(String... arg) {
Th t = new Th();
Thread thread = new Thread(t);
thread.start();
while (true) {
if (pool >= 0)
System.out.println(pool--);
}
}
static void f() {
pool = 5;
System.out.println("main.Main.f:pool=" + pool);
}
}
class Th implements Runnable {
@Override
public void run() {
while (true) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
Main.f();
}
}
}
Output:
5
4
3
2
1
0
main.Main.f:pool=5
main.Main.f:pool=5
main.Main.f:pool=5
main.Main.f:pool=5
I can fix it declaring pool
as volatile
but I can't get why it works 8(
Upvotes: 1
Views: 81
Reputation: 269687
A value written by one thread won't always be read by another. There needs to be a "memory barrier" in order to guarantee visibility, and declaring a field as volatile
is one way to obtain that guarantee.
Loosely speaking, you have to ask for visibility if you want it, otherwise the runtime is free to skip it as an optimization. For example it might use a register to store the main thread's value of pool
instead of updating a field in an object out in the heap. Your code doesn't indicate that other threads should be able to tell the difference, so the runtime is allowed to perform the optimization.
Upvotes: 2
Reputation: 63062
The behavior makes sense: your main()
has no sleep()
in it - so it is able to execute the decrement five times in quick succession. Then after 1000 milliseconds - and every second after - the f()
is called to set the pool to 5.
Upvotes: 0