为什么会出现脏读
java内存模型规定所有的变量都是存在主内存中的,每个线程都有自己的工作内存。线程对变量的所有操作都必须在工作内存中进行,而不能对主存进行操作。并且每个线程不能访问其他线程的工作内存。变量的值何时从线程的工作内存写回主存,无法确定
解决
volatile关键字的作用,保证了变量的可见性(visibility)。被volatile关键字修饰的变量,如果值发生了变更,其他线程立马可见,避免出现脏读的现象。
在执行过程中线程a中的notice发生了变化,但是线程b斌没有感知到这个变化
public class TestVolatile {
private static boolean notice;
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
//线程a
Thread threadA = new Thread( () -> {
for (int i = 0; i < 10; i++) {
arrayList.add("hellolvzi");
System.out.println("线程a想list中添加一个元素,此时list中的元素个数为:" + arrayList.size());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(i == 5) notice = true;
}
});
//线程b
Thread threadB = new Thread( () -> {
while (true){
if (notice){
System.out.println("线程b开始执行自己的任务");
break;
}
}
});
threadB.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadA.start();
}
}
程序运行一直不会结束
打印的结果:
线程a想list中添加一个元素,此时list中的元素个数为:1
线程a想list中添加一个元素,此时list中的元素个数为:2
线程a想list中添加一个元素,此时list中的元素个数为:3
线程a想list中添加一个元素,此时list中的元素个数为:4
线程a想list中添加一个元素,此时list中的元素个数为:5
线程a想list中添加一个元素,此时list中的元素个数为:6
线程a想list中添加一个元素,此时list中的元素个数为:7
线程a想list中添加一个元素,此时list中的元素个数为:8
线程a想list中添加一个元素,此时list中的元素个数为:9
线程a想list中添加一个元素,此时list中的元素个数为:10
添加给状态变量添加volatile关键字
private static volatile boolean notice;
程序会结束打印的结果:
线程a想list中添加一个元素,此时list中的元素个数为:1
线程a想list中添加一个元素,此时list中的元素个数为:2
线程a想list中添加一个元素,此时list中的元素个数为:3
线程a想list中添加一个元素,此时list中的元素个数为:4
线程a想list中添加一个元素,此时list中的元素个数为:5
线程a想list中添加一个元素,此时list中的元素个数为:6
线程a想list中添加一个元素,此时list中的元素个数为:7
线程b开始执行自己的任务
线程a想list中添加一个元素,此时list中的元素个数为:8
线程a想list中添加一个元素,此时list中的元素个数为:9
线程a想list中添加一个元素,此时list中的元素个数为:10