js css html

Java 线程安全问题

2022-09-08  本文已影响0人  Tinyspot

1. 线程安全问题分为多个层面

2. 可见性

分析下面代码的运行结果:

public class Demo {
    static boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (flag) {}
        });
        thread.start();

        TimeUnit.SECONDS.sleep(1);
        flag = false;
    }
}

线程并不会停止,进入死循环
原因是读取的是【工作内存】中的缓存,并不会去访问【主存】中的数据
main 线程修改了主存中的数据,对其他线程(thread-0)不可见

改进1: 让线程暂停 1s, 此时可以读取最新值

while (flag) {
  try {
      TimeUnit.SECONDS.sleep(1);
  } catch (InterruptedException e) {
  }
}

改进2:static volatile boolean flag = true;
volatile 可解决可见性问题,可让一个线程对共享变量的修改,能够及时的被其他线程看到

2.1 关于可见性与原子性

volatile 只能保证看到最新值,不能解决指令交错
synchronized 即可以保证代码块的原子性,同时也保证代码块内变量的可见性;但 synchronized 属于重量级操作,性能相对更低

3. 有序性

JVM 在不影响正确性的前提下,可以调整语句的执行顺序,这种叫【指令重排】
多线程环境下指令重排会影响正确性

指令重排序优化,前提是不能影响结果
分阶段,分工是提升效率的关键

3.1 禁止指令重排

volatile

4. 原子性

i++ 其实是 3 条指令

4. 对象发布和初始化时的安全问题

4.1 处理逸出

上一篇下一篇

猜你喜欢

热点阅读