I have an example like that:
public class MainApp {
private volatile static int MY_INT = 0;
public static void main(String[] args) {
new Thread1().start();
new Thread2().start();
}
static class Thread1 extends Thread {
@Override
public void run() {
while(true) {
MY_INT++;
System.out.println("1 : " + MY_INT);
}
}
}
static class Thread2 extends Thread{
@Override
public void run() {
while(true) {
MY_INT++;
System.out.println("2 : " + MY_INT);
}
}
}
}
And the output is:
1 : 1
2 : 2
1 : 3
2 : 4
1 : 5
1 : 7
1 : 8
1 : 9
1 : 10
2 : 6
1 : 11
1 : 13
I don't understand why after printing 1:10 and the next line is 2:6. Can anyone explain the result? Thanks in advance
There are several issues here:
1:x
and 2:x
one after another, but several 1:x
after each other. volatile
does not help with synchronization. You need real synchronization objects such as AtomicInteger
or the synchronized
keyword. Therefore you may see skipped numbers (not the case in your output, but it may occur). You need the synchronization around both, the ++
and the println()
if you want to see unique numbers println
statements to mix the output on one line The PrintStream in System.out
and the volatile field MY_INT
are independently synchronized, so the following can happen:
Thread 1 Thread 2
read MY_INT = 4
write MY_INT = 5
read MY_INT = 5
read MY_INT = 5
write MY_INT = 6
read MY_INT = 6
println 5
read MY_INT = 6
write MY_INT = 7
read MY_INT = 7
println 7
...
println 6
That is, because the volatile field and the PrintStream returned by System.out are independently synchronized, printing may occur in non-ascending order.
The following could also happen:
Thread 1 Thread 2
read MY_INT = 1
read MY_INT = 1
write MY_INT = 2
write MY_INT = 2
read MY_INT = 2
println 2
read MY_INT = 2
println 2
because ++MY_INT is actually compiled into a read, a computation, and a write. Since volatile reads and writes are separate synchronization actions, other threads may act in between, and mess the counter up.
If you want ascending numbers being printed by separate threads, the easiest way is:
void run() {
while (true) {
synchronized (lock) {
MY_INT++;
System.out.println("1 : " + MY_INT);
}
}
}
where lock
is an object shared by all threads accessing MY_INT.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.