Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it necessary to copy the volatile variable instead of using it directly?

In the book Java concurrency in practice, there is an example of customized thread (See Listing 8.7 in section 8.3.4). I pasted the code below. There is one thing I don't quite understand. That is, the run() method copies the volatile variable debugLifecycle before using it. And it has a comment Copy debug flag to ensure consistent value throughout. Is there any need to copy the variable here? If yes, why?

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());
        }
    }
}
like image 743
adarliu Avatar asked Dec 26 '22 23:12

adarliu


1 Answers

The volatile keyword generally means that the variable is accessed by multiple threads. So you make a copy of it's state once. If, while you are running, another thread modifies it, your copy will be unaffected.

Otherwise it might be the case that the first log.log() gets executed, but not the finally clause's log.log(). Which could be confusing or incorrect behavior.

Even if debugLifecycle were not volatile in a few cases it might still be better to use a copy. But volatile is a "red flag" that this variable might change at any time.

like image 89
user949300 Avatar answered Jan 14 '23 14:01

user949300