volatile
volatile:一致性
static:唯一性
final:持续性
volatile与Runnable
在class implements Runnable时,如果在class中定义了volatile变量,为使该变量能够在多线程下被所有线程读写,即保证变量的唯一性,需要加上static。
如下例,在SafeShutdownThread中,thread2中修改线程two的变量on为false。由于on为static volatile变量,线程three和four通过主内存发现了变量的变化。
线程
线程类Runner implements了Runnable,并定义了一个static volatile的boolean变量on。在下面的测试main线程中,通过Runner的构造函数得到的多个线程具有共同唯一的变量on,并且该变量必须从主内存中读取。如果变量on定义缺少volatile,虽然保证了唯一性,但无法阻止程序优化,从工作内存中读取变量。如果缺少static,每个new出来的线程都有单独的变量,因此线程间无法通过主内存相互通信。
package interrupt;
public class Runner implements Runnable {
private static volatile boolean on = true;
@Override
public void run() {
int i = 0;
while (on && !Thread.currentThread().isInterrupted()) {
i++;
}
System.out.println(Thread.currentThread().getName() + ", i = " + i);
}
public void cancel() {
on = false;
}
public boolean getValue() {
return on;
}
}
测试
package interrupt;
public class SafeShutdownThread {
public static void main(String[] args) throws InterruptedException {
// interrupting signal interrupts thread
Runner one = new Runner();
Thread thread1 = new Thread(one, "Thread-1");
thread1.start();
Thread.sleep(1000);
thread1.interrupt();
// conditions interrupt thread
Runner two = new Runner();
Thread thread2 = new Thread(two, "Thread-2");
thread2.start();
Thread.sleep(1000);
two.cancel();
Runner three = new Runner();
Thread thread3 = new Thread(three, "Thread-3");
thread3.start();
Runner four = new Runner();
Thread thread4 = new Thread(four, "Thread-1");
thread4.start();
Thread.sleep(3000);
three.cancel();
System.out.println(three.getValue());
System.out.println(four.getValue());
}
}
测试结果
Thread-1, i = 590992340
Thread-2, i = 607608508
Thread-3, i = 0
Thread-4, i = 0
false
false