Reputation: 139
public class Test {
static int i = 1;
public static void main(String[] args) {
new Thread(() -> {
long timer = System.nanoTime();
while (true) {
while (System.nanoTime() - timer > 1E9 / 60) {
i++;
timer = System.nanoTime();
}
}
}).start();
long timer = System.nanoTime();
while (true) {
while (System.nanoTime() - timer > 1E9 / 60) {
System.out.println(i);
timer = System.nanoTime();
}
}
}
}
When you start the program the following will be printed in the console:
1,3,4,5,6
Why does the number 2
get skipped? I do not think that it is a timing issue. Any ideas?
Upvotes: 2
Views: 77
Reputation: 81
Two reasons:
static int i
variable is used by two different threads
simultaneously causing unpredictable behaviors due to race
condition. This problem is solved replacing static int i
with
static AtomicInteger i
System.nanoTime() - timer > 1E9 / 60
will not execute the code in the while loop at exactly predictable
times.Upvotes: 1
Reputation: 49606
The output 1,3,4,5,6
doesn't seem to be constant. It may vary due to improper synchronisation.
The reader prints the value when it obtains it. It doesn't care whether the value has been updated or how many times this value has been updated.
The writer changes the value independently of the reader. It doesn't care about the last value the reader has read.
There is a common problem in multithreading called the readers-writers problem. You reproduced the simplest kind of this issue: one reader to one writer.
You ran identical pieces of code in parallel probably assuming they could some kind "overlay" each other as follows:
while (true) {
while (System.nanoTime() - timer > 1E9 / 60) {
i++;
System.out.println(i);
timer = System.nanoTime();
}
}
Unfortunately, it never works that way.
There is no "happened-before" relation, therefore there is no guarantee the "increment-then-print" or "print-then-increment" patterns will always work.
Upvotes: 2
Reputation: 328598
Without any synchronisation, this is an example of valid execution (Thread 1 is the thread you create, Thread 2 is the main thread):
Thread 1 Thread 2
i = 2
print i: 2
i = 3
print i: 3
print i: 3 //loop iterates twice in Thread 2
i = 4
i = 5 //loop iterates twice in Thread 1
print i: 5
i = 6
print i: 5 //main thread doesn't see the update
i = 7
print i: 5 //main thread doesn't see the update
Note that another valid execution, for example, would be to repeatedly print 1.
Upvotes: 2