Why did Goetz not use volatile boolean for Listing 7.20 again?

128 views Asked by At

Here is the code from listing 7.20 in Brian Goetz's Java Concurrency in Practice:

public class CheckForMail {
    public boolean checkMail(Set<String> hosts, long timeout, TimeUnit unit)
            throws InterruptedException { 
        ExecutorService exec = Executors.newCachedThreadPool();
        final AtomicBoolean hasNewMail = new AtomicBoolean(false);

        try { 
            for (final String host : hosts)     
                exec.execute(new Runnable() { 
                    public void run() { 
                        if (checkMail(host)) hasNewMail.set(true);
                    }
                }); 
        } finally { 
            exec.shutdown();
            exec.awaitTermination(timeout, unit); 
        } 
        return hasNewMail.get();
    } 

    private boolean checkMail(String host) { // Check for mail return
        false;
    }
}

Referring this code, Goetz says that "The reason an AtomicBoolean is used instead of a volatile boolean is that in order to access the hasMail flag from the inner Runnable, it would have to be final, which would preclude modifying it" (p. 158).

Why does it have to be final? Couldn't you just make it a non-final boolean volatile?

2

There are 2 answers

2
yshavit On BEST ANSWER

Local variables can't be volatile. If you try to make that change, you'll see it's a compilation error.

Incidentally, as of Java 8, you no longer need to mark the variable as final; as long as it's effectively final (that is, you don't set it after the first time), Java will accept it as if you'd marked it final.

5
John Bollinger On

However why does it have to be final? Couldn't you just make it a non final boolean volatile?

hasNewMail needs to be accessed from the inner Runnable, as Goetz says. That's an instance of an inner class. In the most recent versions of Java, the variable being "effectively final" is a requirement for an inner class to access a local variable of a lexically enclosing method. I think Goetz was writing at a time when the requirement was stronger: that the variable indeed be final. The difference between "effectively final" and final doesn't really matter for this purpose, however, as either way, the variable cannot be modified.

Note, too, that the AtomicBoolean in Goetz's code is final. It itself cannot be modified, but the value stored within can be, and this is how the program works.