简体   繁体   中英

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());
        }
    }
}

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.

The volatile keyword means that it can be accessed and modified by different threads. In java, we have no guarantee about when threads do what (until you get into more complex stuff; start with reading about semaphores and mutexes). So, one thread could change the value of the variable while you another thread is using it. If you're in the middle of of using the variable, and the value changes, this could have a bad effect. So, to prevent that, we copy the value to another variable, and that one will keep the value it had at the time of copying (while the original, volatile one might change).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM