Sharing variable state between threads: “running” flag
Code sample.
public class SomeClass implements Runnable {
private boolean running;
@Override
public void run() {
running = true;
start();
}
public boolean isRunning() {
return running;
}
private void start() {
for (; ; ) {
if (!isRunning()) {
// stop processing items
LOG.warn(“Interrupted and stopping “ + config.getWorkerName());
return;
}
}
}
public void stop() {
running = false;
}
}I will point out one major bug here, leaving design issues for other articles. Simple summary: this WILL NOT work.
If you want to see possible solutions, jump to the bottom of this page.
Problem.
Changing “running” variable value from one thread may or may NOT be visible to other threads, depending on the JVM you use and multiple conditions.
Quote from Java Memory Model:
Changes to fields made by one thread are guaranteed to be visible to other threads only under the following conditions:
A writing thread releases a synchronization lock and a reading thread subsequently acquires that same synchronization lock.
If a field is declared as volatile, any value written to it is flushed and made visible by the writer thread before the writer thread performs any further memory operation (i.e., for the purposes at hand it is flushed immediately). Reader threads must reload the values of volatile fields upon each access.
The first time a thread accesses a field of an object, it sees either the initial value of the field or a value since written by some other thread.
As a thread terminates, all written variables are flushed to main memory. For example, if one thread synchronizes on the termination of another thread using Thread.join, then it is guaranteed to see the effects made by that thread (see §4.3.2).
Solutions.
Quote from StackOverflow to save time:
Your options are:
- volatile. The simplest option. Just add “volatile” to the variable declaration:
private volatile boolean running;