美文网首页
volatile关键字

volatile关键字

作者: mrjunwang | 来源:发表于2018-07-23 15:51 被阅读0次

    1.底层实现原理
     一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

    1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

    2)禁止进行指令重排序。

    volatile关键字禁止指令重排序有两层意思:

    1)当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;

    2)在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行
    下面这段话摘自《深入理解Java虚拟机》:

    “观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令”

    lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:

    1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;

    2)它会强制将对缓存的修改操作立即写入主存;

    3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
    2.volatile关键字无法保证操作的原子性

    
    /**
     * @author jy
     *
     */
    public class VolatileTest {
        //private volatile AtomicInteger i=new AtomicInteger();
        private volatile int i;
        public void increace(){
            i++;
        }
    
        /**
         * @param args
         *<p>Description: </p>  
         */
        public static void main(String[] args) {
    
            VolatileTest test=new VolatileTest();
            for(int i=0;i<100;i++){
            
                new Thread( new Runnable(){
    
                    @Override
                    public void run() {
    
                        for(int j=0;j<10;j++){
                            test.increace();
    
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                    
                }).start();
            }
            
            while(Thread.activeCount()>1){
                Thread.yield();
            }
            System.out.println(test.i);
        }
    
    }
    

    解决方案1:使用AtomicInteger
    java.util.concurrent.atomic包下提供了一些原子操作类,即对基本数据类型的 自增(加1操作),自减(减1操作)、以及加法操作(加一个数),减法操作(减一个数)进行了封装,保证这些操作是原子性操作。atomic是利用CAS来实现原子性操作的(Compare And Swap)

    
    
    import java.util.concurrent.atomic.AtomicInteger;
    
    
    
    /**
     * @author jy
     *
     */
    public class VolatileTest {
        private volatile AtomicInteger i=new AtomicInteger();
        //private volatile int i;
        public void increace(){
            i.getAndIncrement();
        }
    
        /**
         * @param args
         *<p>Description: </p>  
         */
        public static void main(String[] args) {
    
            VolatileTest test=new VolatileTest();
            for(int i=0;i<100;i++){
            
                new Thread( new Runnable(){
    
                    @Override
                    public void run() {
    
                        for(int j=0;j<10;j++){
                            test.increace();
    
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                    
                }).start();
            }
            
            while(Thread.activeCount()>1){
                Thread.yield();
            }
            System.out.println(test.i);
        }
    
    }
    

    解决方案2:increace()加synchronized
    解决方案3:加锁ReentrantLock

    public class VolatileTest {
        //private volatile AtomicInteger i=new AtomicInteger();
        private volatile int i;
        Lock lock=new ReentrantLock();
        public  void increace(){
            lock.lock();
            i++;
            
            lock.unlock();
        }
    
        /**
         * @param args
         *<p>Description: </p>  
         */
        public static void main(String[] args) {
    
            VolatileTest test=new VolatileTest();
            for(int i=0;i<100;i++){
            
                new Thread( new Runnable(){
    
                    @Override
                    public void run() {
    
                        for(int j=0;j<10;j++){
                            test.increace();
    
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                    
                }).start();
            }
            
            while(Thread.activeCount()>1){
                Thread.yield();
            }
            System.out.println(test.i);
        }
    
    }
    

    相关文章

      网友评论

          本文标题:volatile关键字

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