[英]Why is it necessary to copy the volatile variable instead of using it directly?
在實踐中的Java並發性一書中,有一個自定義線程的例子(參見8.3.4節中的清單8.7)。 我粘貼了下面的代碼。 有一點我不太明白。 也就是說, run()
方法在使用之前復制volatile變量debugLifecycle
。 它有一個注釋復制調試標志,以確保始終如一的價值 。 有沒有必要在這里復制變量? 如果是,為什么?
public class MyAppThread extends Thread {
public static final String DEFAULT_NAME = "MyAppThread";
private static volatile boolean debugLifecycle = false;
public MyAppThread(Runnable r) {
this(r, DEFAULT_NAME);
}
public MyAppThread(Runnable runnable, String name) {
super(runnable, name + "-" + created.incrementAndGet());
setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t,
Throwable e) {
log.log(Level.SEVERE,
"UNCAUGHT in thread " + t.getName(), e);
}
});
}
public void run() {
// Question: why copy the volatile variable here?
// Copy debug flag to ensure consistent value throughout.
boolean debug = debugLifecycle;
if (debug) log.log(Level.FINE, "Created " + getName());
try {
alive.incrementAndGet();
super.run();
} finally {
alive.decrementAndGet();
if (debug) log.log(Level.FINE, "Exiting " + getName());
}
}
}
volatile
關鍵字通常表示該變量由多個線程訪問。 所以你要復制一次狀態。 如果在您運行時,另一個線程修改它,您的副本將不受影響。
否則可能是第一個log.log()
被執行,而不是finally子句的log.log()
。 這可能是令人困惑或不正確的行為。
即使debugLifecycle在少數情況下是不揮發它仍然可能會更好使用副本。 但是volatile
是一個“紅旗”,這個變量可能隨時改變。
volatile關鍵字意味着它可以被不同的線程訪問和修改。 在java中,我們無法保證線程什么時候做什么(直到你進入更復雜的東西;從讀取信號量和互斥量開始)。 因此,當另一個線程正在使用它時,一個線程可以更改變量的值。 如果您正在使用變量,並且值發生變化,則可能會產生不良影響。 因此,為了防止這種情況,我們將值復制到另一個變量,並且該值將保留復制時的值(而原始的,易變的值可能會更改)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.