One common example for using volatile
is to use a volatile boolean variable
as a flag to terminate a thread. If
you've started a thread, and you want
to be able to safely interrupt it from
a different thread, you can have the
thread periodically check a flag. To
stop it, set the flag to true. By
making the flag volatile, you can
ensure that the thread that is
checking it will see it has been set
the next time it checks it without
having to even use a synchronized
block.
"interrupt from a different thread", then how would you answer, why you need 'volatile' field to hold the cancellation state when the same thread starts the thread and invokes cancel?
package net.jcip.examples;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.math.BigInteger;
import java.util.;
import java.util.concurrent.;
import net.jcip.annotations.*;
/**
* PrimeGenerator
*
* Using a volatile field to hold cancellation state
*
* @author Brian Goetz and Tim Peierls
*/
@ThreadSafe
public class PrimeGenerator implements Runnable {
private static ExecutorService exec = Executors.newCachedThreadPool();
@GuardedBy("this") private final List<BigInteger> primes
= new ArrayList<BigInteger>();
private volatile boolean cancelled;
public void run() {
BigInteger p = BigInteger.ONE;
while (!cancelled) {
p = p.nextProbablePrime();
synchronized (this) {
primes.add(p);
}
}
}
public void cancel() {
cancelled = true;
}
public synchronized List<BigInteger> get() {
return new ArrayList<BigInteger>(primes);
}
static List<BigInteger> aSecondOfPrimes() throws InterruptedException {
PrimeGenerator generator = new PrimeGenerator();
exec.execute(generator);
try {
SECONDS.sleep(1);
} finally {
generator.cancel();
}
return generator.get();
}
}