[英]System.out.println with java volatile
我有一個這樣的例子:
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);
}
}
}
}
輸出為:
1 : 1
2 : 2
1 : 3
2 : 4
1 : 5
1 : 7
1 : 8
1 : 9
1 : 10
2 : 6
1 : 11
1 : 13
我不明白為什么在打印1:10后下一行是2:6。 誰能解釋結果? 提前致謝
這里有幾個問題:
1:x
和2:x
,而是幾個接一個的1:x
。 volatile
不利於同步。 你需要真正的同步對象,如AtomicInteger
或synchronized
關鍵字。 因此,您可能會看到跳過的數字(輸出中不是這種情況,但是可能會發生)。 如果要查看唯一的數字,則需要圍繞++
和println()
進行同步 println
語句在一行上混合輸出 System.out
的PrintStream和volatile字段MY_INT
是獨立同步的,因此可能發生以下情況:
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
也就是說,由於System.out返回的volatile字段和PrintStream是獨立同步的,因此打印可能以非升序順序進行。
也可能發生以下情況:
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
因為++ MY_INT實際上被編譯為讀取,計算和寫入。 由於易失性讀取和寫入是單獨的同步操作,因此其他線程可能在兩者之間起作用,並使計數器混亂。
如果要通過單獨的線程打印升序數字,最簡單的方法是:
void run() {
while (true) {
synchronized (lock) {
MY_INT++;
System.out.println("1 : " + MY_INT);
}
}
}
其中lock
是所有訪問MY_INT的線程共享的對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.