Java 可见性
内存模型
主存
所有线程都可以访问
本地内存
每个线程私有的内存
- java 的所有变量都存储在主内存中
- 每个线程有自己独的工作内存,保存了该线程使用到的变量副本,是对主内存中变量的一份拷贝
- 每个线程不能访问其他线程的工作内存,线程间变量传递需要通过主内存来完成
- 每个线程不能直接操作主存,只能把主存的内容拷贝到本地内存后再做操作(这是线程不安全的本质),然后写回主存
可见性的方法
volatile
这种方式可以保证每次取数直接从主存取
它只能保证内存的可见性,无法保证原子性
它不需要加锁,比 synchronized 更轻量级,不会阻塞线程
验证测试
public class testRun implements Runnable{ public volatile Boolean flag=false; public ArrayListarr =new ArrayList<>(); @Override public void run() { while (true){ if(arr.size()>0){ break; } } } }
public static void main(String[] args) throws InterruptedException {
testRun testRun = new testRun();
new Thread(testRun).start();
Thread.sleep(1000);
testRun.flag=true;
testRun.arr.add("123");
}
测试 发现arr 不加volatile 主线程的修改不能使 测试线程正确停止
ArrayList 是线程不安全的 如果我们使用线程安全类呢
public class testRun implements Runnable{
public volatile Boolean flag=false;
public ArrayList
public Vector
@Override
public void run() {
while (true){
if(vec.size()>0){
break;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
testRun testRun = new testRun();
new Thread(testRun).start();
Thread.sleep(1000);
testRun.flag=true;
testRun.vec.add("123");
}
测试发现是可以正确停止
那
public HashMap
public Hashtable
public ConcurrentHashMap
测试发现 HashMap 需要加volatile 关键字才可以正确停止 线程安全的hashtable与concurrentHashMap则不需要 具体为啥 不清楚