美文网首页js css html
Java 线程安全问题

Java 线程安全问题

作者: Tinyspot | 来源:发表于2022-09-08 08:15 被阅读0次

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

    • 可见性 volatile, Synchronized
    • 有序性 volatile, Synchronized
    • 原子性 AtomicInteger, Lock, Synchronized

    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 处理逸出

    • 返回“副本”
    • 工厂模式

    相关文章

      网友评论

        本文标题:Java 线程安全问题

        本文链接:https://www.haomeiwen.com/subject/irzjvrtx.html