文章目录

      • 线程不安全之volatile关键字
          • 可见性
          • 有序性
      • 分析一下单例模式

线程不安全之volatile关键字

上篇博文讲了线程不安全问题
https://editor.csdn.net/md/?articleId=111461834

可见性
  • 就是说, 在多线程的环境下,某个共享变量A被其中一个线程修改了,其他线程就会知道有一个线程修改了这个共享变量A,然后其他线程若是要使用这个共享变量,就会直接去内存中去读取整个共享变量,而不是从自己的空间中去读取这个变量A。(线程自己的内存区域中存储着这个变量A的缓存地址,当他发现有别的线程去修改变量A的时候,就会强制让自己内存区域中的这个变量A的缓存地址无效,然后去从主存中去访问这个变量A,缓存和主存的内容是一致的)
  • 被volatile申明的变量就具有可见性的性质
有序性
  • 在我们基础的理解上 Java的代码执行是顺序执行的,但是在虚拟机里代码可能会进行重排序

     int a = 1;  //1
     int b = 1;  //2
     a++;        //3
     b++;        //4
    

    上面四行代码,无论先执行第三行 还是第四行 都不会最终对a的值和b的值产生影响,所以在虚拟机执行这些代码的时候就可能进行重排序。但是如果第三行代码需要执行的时候需要消耗5ms,但第四行只需要消耗1ms,所以当然就会先执行第四行。

  • 但是在多线程里面就会可能出现问题了

    boolean static ready = false;
    int static x = 0;
    Thread t  = new Thread(new Runnable() { 
         @Override
         public void run(){ 
             if (ready) { 
                 t++;
             } 
         }
    });
    t.start;
    ready = true;  // 1
    System.out.println(x);         // 2 
    

    如果第1和第2发生重排序的话就会发生线程不安全问题。

    但是 volatile 修饰的关键字只能让自己本身不发生重排序。也就是说我只呆在自己的位置,并且让我后面的不去前面 ,前面的不去后面,起到一个屏障的作用。 但是无法阻碍前面的和前面(后面的和后面的)被重排序。

分析一下单例模式

public class lesson4 { 
    private static volatile lesson4  LS= null;

    // 双重校验锁
    public void getLesson() { 
        if (LS == null) {   // 1 
            synchronized (lesson4.class) {  // 2
                if (LS == null) {  // 3
                    LS = new lesson4(); // 4
                }
            }// 5
        }
    }
}

假设有线程 A 和 线程 B 同时去执行 getLesson() 方法

  1. 第一种可能就是 A B两个 线程都执行到了 第2行代码 然后去抢占锁,假设A线程抢占锁成功,然后去执行3 4 行代码,最后执行第五行代码代码也就是释放锁之前,B线程一直就被卡在了第二行代码。但是当他获取锁之后,发现LS != null ,volatile关键字让他从内存中看见了了LS不为null,已经被new了,然后B线程就释放锁。

  2. synchronized 保证了操作是原子的,也就是说当有一个线程去new LS的时候,其他线程是无法LS进行操作的,而第三行又保证了不会重复new

  3. 但是抢占锁这个操作是挺耗费cpu资源的,第1行的就是为了提高效率,若是已经new了一个LS,那木我们就可以直接判断不为null,不进去抢占锁了,减少了cpu资源的耗费

  4. 我们知道 new 一个对象在JVM虚拟机中可以分为四步走,第一就是类加载过程,知道这个类会耗费多少内存空间,第二步就是开辟内存空间,第三步就是在空间上创建这个对象,第四步就是把这个对象赋值给字段。 volatile 关键字保证初始化对象和对象引用的时候不会进行指令重排序。

本文地址:https://blog.csdn.net/shadow___h/article/details/112000485