浅谈Volatile

javavolatile
我们用一段简单的代码来开头
Java代码  收藏代码

    public int i = 0; 
    public void increase(){  
        i++; 
    } 
    //getter 


    以上这段代码在多线程高并发的状态下能否保证所取得的i是所期待的值,答案肯定是不能的,因为对JAVA来说数据的操作是非原子性的。还有的就是部份人认为给变量i加上volatile关键字就能保证了数据操作的原子性,这显然是错误的。要记住volatile关键字只保证其可见性,也就是说当某线程修改了i的值,修改后的值对其它线程来说是立即可见的。下面我们分析通过increase()方法的字节码来解释。
Java代码  收藏代码

    public void increase(); 
    public void increase(); 
       flags: ACC_PUBLIC 
       Code: 
        stack=3, locals=1, args_size=1 
           0: aload_0 
           1: dup 
           2: getfield      #2                  // Field i:I 
           5: iconst_1 
           6: iadd 
           7: putfield      #2                  // Field i:I 
          10: return 
        LineNumberTable: 
          line 5: 0 
          line 6: 10 


    编号2到7这几行指令就是i++;的,首先getfield获取到了i的值并把它压入栈顶,在这里如果i变量有加volatile关键字,则能保证i的正确性,因为无论之前有几个线程对i作了修改,它总是能够第一时间得知。如果是普通变量的话,比如A线程对变量i修改完新值后要把它重写回主内存中,其它线程要想得知i的新值要在A线程重写回主内存之后,对这感兴趣的可以看下主线程和工作线程相关的内容。 接下来就是引发问题的关键之处了,假如当A线程准备执行相加指令时,其它线程已经把i值修改了,而A线程的操作数栈顶的值已经变为脏数据了,在执行putfield后把不正确的数据同步回主内存里。

你可能感兴趣的:(java,多线程)