APP下载
报价宝  ›  科技  › 

volatile变数

报价宝 来源:baojiabao.com 发布时间:2019-08-21 01:50:00 09月19日更新
报价宝综合消息volatile变数

关键字volatile是虚拟机器提供的一种轻量级的同步机制,但在做多执行绪开发时,大部分的人都不太习惯喜欢用volatile,而是直接用关键字synchronized来进行同步。但有些时候在解决执行绪安全问题时,使用volatile关键字要比使用synchronized同步函式更好一些。下面我们详细分析一下在Java中关键字volatile到底是一个什么样的东东,底层是怎么实现的。

在JMM中虚拟机器对volatile关键字专门定义了一些特殊的访问规则,来实现执行绪的轻量级同步。当变数是一个volatile变数时,它就会具有两种特殊的特性。

第一个特性就是保证此变数对所有执行绪的可见性。可见性的意思是说当一个执行绪修改了volatile变数时,对于其它执行绪可以立即知道修改后的值。而普通变数则不具有此特性,普通变数只能通过主内存来完成。也就是说如果某一个执行绪修改了普通变数的值,只能向主内存同步后,其它执行绪在从主内存中拷贝后,才可以得到新的普通变数的值。虽然volatile变理具有可见性,但在使用volatile变数时,并不能保证不会出现执行绪安全问题。我们请看下面的程式码。

按照程式码的逻辑,每个执行绪都会呼叫1000次increase()方法,也就是每一个执行绪都会执行1000次volatile变数的自增。并且我们开启了10个执行绪,按照volatile变数可见性的分析,在正常情况下最后输出的值就应该是10000。但实际的结果却小于10000这是为什么呢?

问题的原因就是虽然volatile变数具有可见性,能够保证其它执行绪立即获取到更新后的值。但问题的原因却是自增运算导致的。也就是race++。在Java中自增运算并不是原子性的操作,所以在程式执行自增运算时,其它执行绪也有可能执行。我们使用javap命令来检视一下编译后的字节码就明白了其中的缘由了。

我们主要看increase()方法中的字节码即可。在字节码中使我们知道虽然在源代码中我们只写了一条语句,但是在字节码执行时,是需要5条指令来实现自增运算的。虽然volatile变数可以保证在虚拟机器执行字节码时变数是最新的值,但是并不能保证在执行其它指令时,别的执行绪不在更新volatile变数。如果在此执行绪没有执行自增运算指令时,其它执行绪已经对volatile变数进行了修改,那么在此执行绪在执行自增运算时,得到的volatile变数已经是过期的了,既然是过期的值,那就一定会比真正的值要小,于是此执行绪就把已经过期的volatile变数的值同步到了主内存中,所以程式在执行时,最后的执行结果会比预计执行的值要小。

使用volatile变数的别一种特性就是禁止指令重排序优化。重排序的意思是说CPU在执行指令时,为了进行优化处理,常常会对指令进行重新排序,也就是说CPU执行指令的顺序在重排序后是有可能和程式源代码中的顺序是不一样的,但CPU并不会影响程式原有的执行结果。

文章标签: 报价宝 降噪耳机价格 耳机价格 红米手机价格 华为手机价格 小米手机价格 电视机价格 笔记本电脑价格 笔记本价格 汽车价格 手机价格 笔记本电脑价格 华为手机价格 红米手机价格 降噪耳机价格