zoukankan      html  css  js  c++  java
  • volatile关键字解析(一)

    引起线程并发问题,可以简单的总结为以下三条:

    • 原子性问题
    • 可见性问题
    • 有序性问题(重排序问题)

    原子性问题

    什么是原子性?

    原子性,即一个操作或者多个操作,要么全部执行并且执行过程中不会被任何因素打断,要么全部都不执行。

    如常见的银行转账、count++操作等,都必须具备原子性才能保证不出现意外。

    A向B转账100元,需要保证两步:A账户减100,B账户加100,如果有任何一个发生意外,总有不满意的一方,A账户减了100,B账户没有加100,客户肯定不满意;A账户由于某种原因没有减100,但是B账户却加了100,银行此时肯定也不干(毕竟是国内,你懂得)。

    可见性问题

    什么是可见性?

    可见性是指当多个消除访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改的值。

    同样举个例子来说明一下:

    public class RunThread extends Thread {
    
        private boolean isRunning = true;
    
        public boolean isRunning() {
            return isRunning;
        }
    
        public void setRunning(boolean isRunning) {
            this.isRunning = isRunning;
        }
    
        @Override
        public void run() {
            System.out.println("进入到run方法中了");
            while (isRunning == true) {
            }
            System.out.println("线程执行完成了");
        }
    }
    public class TestRun
    {
        public static void main(String[] args) {
            try {
                RunThread thread = new RunThread();
                thread.start();
                Thread.sleep(100);
                thread.setRunning(false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }  
    }

    我们会发现,RunThread线程无法正常结束了,进入了死循环了。这是由于在主线程中修改的isRunning值,并没有及时对RunThread线程感知到,这就是可见性的问题,由于主线程修改了之后,RunThread线程并没有立即能看到。

    有序性问题
    什么是有序性?
    有序性即程序执行的顺序按照代码的先后顺序执行。

    int a = 0;
    int b = 0;
    a = 1; //语句1
    b = 2; //语句2
    int c = a * a;//语句3 
    int d = b + c;//语句4

    从上述代码看,语句1在语句2之前执行,但是对于JVM来说情况未必如此,这就是指令重排序。

    volatile使用场景
    当需要避免并发时发生意想不到的结果,必须要保证以上三条都满足,否则极有可能得到你不想要的结果,我们常用的操作有synchronized和lock来保证这些情况,但是有些情况下,我们其实可以使用轻量级并发volatile关键字,
    但是它并不能保证原子性操作,因此,volatile并不能替代synchronized。
    关于volatile使用的场景:

    • 对变量的写操作不依赖于当前值
    • 该变量没有包含在具有其他变量的不变式中

    常见的场景有:

    • 状态标记变量(如上文提到的RunThread例子中可以对isRunning变量使用volatile关键字)
    • 单例中双重检查锁,见(http://www.cnblogs.com/woniu4/p/8287484.html)

    什么是指令重排序呢?简单多说,就是处理器为了提升程序的运行效率,可能对输入的代码进行优化,它不保证程序各个语句的执行先后顺序同代码中的顺利一致,但保证最后的结果和顺序执行是一直的。
    由于语句4依赖于语句3,则两者的顺序是不会调整的。

  • 相关阅读:
    WPF关于改变ListBoxItem的颜色的注意事项以及如何找到ListBox中的ItemsPanel
    WPF中关于配置文件的读取
    C++虚函数和虚函数表
    gdb调试技巧
    libevent和基于libevent的网络编程
    Reactor模式详解
    Ubuntu Linux 下文件名乱码(无效的编码)的快速解决办法
    Linux进程间通信——使用共享内存
    Linux进程间通信——使用信号量
    布隆过滤器(Bloom Filter)详解
  • 原文地址:https://www.cnblogs.com/woniu4/p/8329618.html
Copyright © 2011-2022 走看看