博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java中的volatile关键字
阅读量:5755 次
发布时间:2019-06-18

本文共 1712 字,大约阅读时间需要 5 分钟。

volatile关键字的作用是保证多线程执行的同步性。

在java虚拟机的内存模型中,有主内存和工作内存的概念,每个线程对应一个工作内存,并共享主内存的数据,下面看看操作普通变量和volatile变量有什么不同:

1、对于普通变量:读操作会优先读取工作内存的数据,如果工作内存中不存在,则从主内存中拷贝一份数据到工作内存中;写操作只会修改工作内存的副本数据,这种情况下,其它线程就无法读取变量的最新值。

2、对于volatile变量,读操作时JMM会把工作内存中对应的值设为无效,要求线程从主内存中读取数据;写操作时JMM会把工作内存中对应的数据刷新到主内存中,这种情况下,其它线程就可以读取变量的最新值。

volatile变量的内存可见性是基于内存屏障(Memory Barrier)实现的,什么是内存屏障?内存屏障,又称内存栅栏,是一个CPU指令。在程序运行时,为了提高执行性能,编译器和处理器会对指令进行重排序,JMM为了保证在不同的编译器和CPU上有相同的结果,通过插入特定类型的内存屏障来禁止特定类型的编译器重排序和处理器重排序,插入一条内存屏障会告诉编译器和CPU:不管什么指令都不能和这条Memory Barrier指令重排序。

CPU为了提高处理性能,并不直接和内存进行通信,而是将内存的数据读取到内部缓存(L1,L2)再进行操作,但操作完并不能确定何时写回到内存,如果对volatile变量进行写操作,当CPU执行到Lock前缀指令时,会将这个变量所在缓存行的数据写回到内存,不过还是存在一个问题,就算内存的数据是最新的,其它CPU缓存的还是旧值,所以为了保证各个CPU的缓存一致性,每个CPU通过嗅探在总线上传播的数据来检查自己缓存的数据有效性,当发现自己缓存行对应的内存地址的数据被修改,就会将该缓存行设置成无效状态,当CPU读取该变量时,发现所在的缓存行被设置为无效,就会重新从内存中读取数据到缓存中。

程序运行时需要CPU、高速缓存、内存三个部件协同工作,线程A把内存中的变量x读到了高速缓存,线程B现在修改了变量x。内存中的x虽然变了,但是线程A依旧认为高速缓存中的x是最新的。这就影响了线程之间的同步。

volatile关键字的作用就是:如果线程B修改了变量x,那么线程A的高缓中的x就失效了,需要从内存中重新加载。

单例模式中使用volatile更稳妥,这种单例实现方式叫做“double check”,在进入synchronized区域之前检查一次,进入之后再检查一次。外层的if能够避免所有线程都进入synchronized区域,从而避免了线程同时等待一个锁,内层的if用于准确判断,免得其它线程已经创建了单例。

class Singleton {    private volatile static Singleton instance;    public static Singleton getInstance() {        if (instance == null) {            syschronized(Singleton.class) {                if (instance == null) {                    instance = new Singleton();                }            }        }        return instance;    } }

另外一种依赖类加载机制的单例模式实现方法

public class Singleton {      static class SingletonHolder {          static Singleton instance = new Singleton();      }            public static Singleton getInstance(){          return SingletonHolder.instance;      }  }

参考资料

转载地址:http://sockx.baihongyu.com/

你可能感兴趣的文章
如何自学人工智能?
查看>>
阿里云 oss JavaScript客户端签名文件上传 vue2.0
查看>>
快速掌握阿里云 E-MapReduce
查看>>
Mysql索引原理浅析
查看>>
offsetWidth,clientWidth,width,scrollWidth之间的区别
查看>>
生辰八字取名的方法
查看>>
圆角输入框”背景“
查看>>
Linux基础(day43)
查看>>
LNMP架构介绍、MySQL安装、PHP安装与Nginx介绍
查看>>
Day28 awk工具讲解
查看>>
Spring配置补充
查看>>
Servlet 3.0 新特性 无 web.xml配置
查看>>
大数据安全之Hadoop生态圈背后不可忽视的隐藏“凶险”
查看>>
VCF比对工具的安装及使用
查看>>
Idea Spring boot webmvc Thymeleaf namespace not found
查看>>
最简单的docker教程:在docker里运行nginx服务器
查看>>
区块链100讲:总被提起的拜占庭问题到底是什么鬼?
查看>>
48小时区块链黑客马拉松(成都)
查看>>
“零确认”有望助力BCH得到广泛应用
查看>>
Firefox浏览器xpath工具插件(高版本Firefox不支持)
查看>>