码迷,mamicode.com
首页 > 编程语言 > 详细

JAVA并发编程:volatile的使用及其原理

时间:2019-04-14 18:02:40      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:编程   margin   mamicode   检查   因此   需要   []   空间   sync   

一、volatile的使用

 1、防止重排序

  • 在并发环境下实现单例模式,我们通常可以采用双重检查加锁(DCL)的方式来现实:
    public class Singleton {
    
        public static volatile Singleton singleton;
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if(singleton == null) {
                synchronized (singleton) {
                    if(singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }

    实例化一个对象其实可以分为三个步骤:

(1)分配内存空间

(2)初始化对象

(3)将内存空间的地址赋值给对应的引用。

但是由于操作系统可以对指令进行重排序,所以上面的过程也可能变成如下过程:

(1)分配内存空间

(2)将内存空间的地址赋值给对应的引用。

(3)初始化对象

如果这是个流程,多线程环境下就可能将一个未初始化的对象引用暴露出来,从而导致不可预料的结果。因此,为了防止这个过程的重排序,我们需要将变量设置为volatile类型的变量。

2、实现可见性

  • 可见性问题主要指一个线程修改了共享变量值,而另一个线程却看不到。引起可见性问题的主要原因就是每个线程拥有自己的高速缓存区——线程工作内存。volatile关键字能有效解决这个问题。
    public class VolatileTest {
    
        int a = 1;
        int b = 2;
    
        public void change() {
            a = 3;
            b = a;
        }
    
        public void print() {
            System.out.println("b=" + b + ";a=" + a);
        }
    
        public static void main() {
            final VolatileTest bean = new VolatileTest();
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    bean.change();
                }
            }).start();
    
    
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    bean.print();
                }
            }).start();
        }
    
        public static void main(String[] args) {
            for(int i = 0; i < 10; i++) {
                main();
            }
        }
    }

 直观上说,这段代码的结果只可能有两种:b=3;a=3或者b=2;a=1。不过运行上面的代码,却出现了三种情况:

技术图片

 

 

 

JAVA并发编程:volatile的使用及其原理

标签:编程   margin   mamicode   检查   因此   需要   []   空间   sync   

原文地址:https://www.cnblogs.com/lynn16/p/10705895.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!