原子性和易变性
要理解黄色标注的内容那得 了解一下java中的内存模型:
Java内存模型FAQ : http://ifeve.com/jmm-faq/
同步和java内存模型: http://ifeve.com/syn-jmm/
java内存模型指南: http://ifeve.com/jmm-cookbook/
深入理解java内存模型: http://ifeve.com/java-memory-model-0/
首先看完java内存模型我们了解到:java线程运行时分主存和线程的工作内存,线程的工作内存(相当于是缓存)会有主存的共享变量的副本,所有的修改和读取都是针对于线程的工作线程的。其实工作线程只是一个抽象的概念不一定存在
看完这个你可能会有一点疑问?既然所有的线程读取和修改都是针对工作线程 那么他就应该是线程安全的啊 因为各个线程工作内存各自不影响啊!其实
public class IntGeneratorActual extends IntGenerator {
private int val = 0;
@Override
public int next() {
System.out.println("Thread:" + Thread.currentThread().getName() + " read val:" + val);
val++;
System.out.println("Thread:" + Thread.currentThread().getName() + " yield before:" + val);
Thread.yield();
System.out.println("Thread:" + Thread.currentThread().getName() + " yield after:" + val);
val++;
return val;
}
public int getVal() {
return val;
}
}
public class EvenChecker2 implements Runnable {
private IntGeneratorActual actual;
public EvenChecker2(IntGeneratorActual actual) {
super();
this.actual = actual;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
int a = actual.getVal();
if (a % 2 != 0) {
System.out.println("get not steady val:" + a);
actual.cancel();
break;
}
}
}
}
public class JMMTest1 implements Runnable {
private IntGeneratorActual intGeneratorActual;
public JMMTest1(IntGeneratorActual intGeneratorActual) {
super();
this.intGeneratorActual = intGeneratorActual;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (!intGeneratorActual.isCanceled()) {
int a = intGeneratorActual.next();
System.out.println("Thread:"+Thread.currentThread().getName()+" next:"+a);
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
IntGeneratorActual actual = new IntGeneratorActual();
Runnable target = new JMMTest1(actual);
Runnable target2 = new EvenChecker2(actual);
for (int i = 0; i < 4; i++) {
executorService.execute(target);
}
executorService.execute(target2);
executorService.shutdown();
}
}
根据输出可以看出,你根本不知道 缓存什么时候会把 值写进 主存,也不知道什么时候 线程会读取主存中的值。你根本不知道线程的工作线程是否存在。(本人能力有限是在理解不了这一些).
我总结如下:线程原子性的问题的时候就当没有线程的工作内存 所有的操作都像是直接针对主存
线程可见性的问题的时候 是由于重排序导致的