[英]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.