我讀過很多文章認爲System.out.println()
使代碼有些線程安全,所以模擬比賽System.out.println()
應該從代碼中刪除。易變與Java中的System.out.println()
現在的PrintStream
的write()
方法上this
同步寫入流之前,所以每次write()
被稱爲然後持有鎖和釋放。 PrintStream的
public void write(int b) {
try {
synchronized (this) { //acquires a lock
ensureOpen();
out.write(b);
if ((b == '\n') && autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
但
write()
方法會影響比賽的行爲?
假設:
boolean flag = true;
Thread 1:
System.out.println();
flag = false;
System.out.println();
Thread 2:
System.out.println();
while(flag){
System.out.println();
}
現在,如果我們看到那麼這兩個線程都鎖定即this
(PrintStream的)相同的對象,現在作爲flag
包含兩個sysouts
,這是獲取和釋放在它們之間鎖,然後flag
值將從緩存中刷新並更新到其他線程可以看到它的內存中。
因此,模擬比賽是困難的是有理論上的可能性,這個代碼將是線程安全的,線程2將看到對flag
所做的更改?
如果是,那麼可以在volatile
同樣的效果可以用System.out.println();
實現?
線程安全是不一樣的「鎖定」。有很多算法在那裏能見度是你所需要的。如你的例子所示,其他線程確實看到了更新後的標誌值(如果沒有println,那麼獲得無限循環是完全可以接受的)。給定的可見性保證是否足夠取決於算法。 – Voo