Java的挥发性修饰符

不久前,我编写了一个Java servlet过滤器,该过滤器在其init函数中加载配置(基于web.xml的参数)。 筛选器的配置缓存在私有字段中。 我在字段上设置了volatile修饰符。

后来,当我检查Sonar公司以查看是否在代码中发现任何警告或问题时,得知使用volatile违反了规定,我感到有些惊讶。 解释为:

通常使用关键字“ volatile”来微调Java应用程序,因此需要Java内存模型的专业知识。 而且,它的作用范围还不太清楚。 因此,volatile关键字不应用于维护目的和可移植性。

我同意volatile是许多Java程序员所不知道的。 对于一些甚至未知。 不仅因为它从一开始就没有使用太多,还因为它的定义自Java 1.5起就发生了变化。

让我稍微回顾一下Sonar的违规行为,首先解释volatile在Java 1.5及更高版本中的含义(直到撰写本文时Java 1.8)。

什么是挥发物?

尽管volatile修饰符本身来自C,但在Java中它具有完全不同的含义。 这可能无助于加深对它的理解,使用谷歌搜索挥发物可能会导致不同的结果。 让我们快速迈出第一步,看看volatile在C语言中的含义。

在C语言中,编译器通常假定变量无法自行更改值。 尽管这是默认行为,但有时变量可能表示可以更改的位置(例如硬件寄存器)。 使用易失性变量指示编译器不要应用这些优化。

回到Java。 C中的volatile的含义在Java中将毫无用处。 JVM使用本机库与操作系统和硬件进行交互。 此外,将Java变量指向特定地址根本是不可能的,因此变量实际上不会自行更改值。

但是,JVM上变量的值可以由不同的线程更改。 默认情况下,编译器假定变量不会在其他线程中更改。 因此,它可以应用优化,例如对存储器操作重新排序以及将变量缓存在CPU寄存器中。 使用易失性变量指示编译器不要应用这些优化。 这样可以保证读取线程始终从内存(或共享缓存)中读取变量,而不从本地缓存中读取变量。

原子性

更进一步,关于32位JVM的volatile使写入到64位可变原子(如longdouble )成为可能。 要写入变量,JVM会指示CPU将操作数写入内存中的某个位置。 使用32位指令集时,如果变量的大小为64位怎么办? 显然,该变量必须用两条指令(一次32位)写入。

在多线程方案中,另一个线程可能会在写入过程中读取变量。 此时,仅写入变量的前半部分。 这种争用条件可以通过可变的方式来防止,从而有效地使对32位体系结构的64位变量进行原子写入。

请注意,上面我谈到的是而不是更新 。 使用volatile不会使更新原子化。 例如,当i易失时, ++i将从堆或L3缓存中读取i的值到本地寄存器inc中,然后将该寄存器写回到i的共享位置。 在读写之间, i可能会被另一个线程更改。 在读写指令周围加一个锁,使更新成为原子操作。 或更妙的是,使用concurrent.atomic包中原子变量类的非阻塞指令。

副作用

volatile变量在内存可见性方面也有副作用。 当线程读取volatile变量时,不仅对volatile变量的更改对其他线程可见,而且导致更改的代码的任何副作用也可见。 或更正式地说,易失性变量与该变量的后续读取之间建立事前关联。

即,从内存可见性的角度来看,有效地写入易失性变量就像退出同步块并读取易失性变量就像进入变量一样。

选择易失性

回到我使用volatile一次初始化配置并将其缓存在私有字段中的情况。

到目前为止,我相信确保此字段对所有线程可见的最佳方法是使用volatile。 我本来可以使用AtomicReference 。 由于该字段仅被写入一次(在构造之后,因此不可能是最终的),因此原子变量传达了错误的意图。 我不想使更新原子化,我想使缓存对所有线程可见。 对于它的价值,原子类也使用volatile。

关于声纳法则的思考

既然我们已经了解了volatile在Java中的含义,那么让我们进一步讨论一下Sonar规则。

在我看来,此规则是Sonar之类的工具配置中的缺陷之一。 如果您需要跨线程共享(可变)状态,那么使用volatile可能是一件非常好的事情。 当然,您必须将此保持在最低水平。 但是,此规则的结果是,不了解什么是挥发性的人会遵循建议不要使用挥发性。 如果他们有效地删除修饰符,则会引入竞争条件。

我确实认为使用未知或危险的语言功能时自动升起红色标记是个好主意。 但是,也许只有当有更好的替代方案来解决同一问题时,这才是一个好主意。 在这种情况下,volatile没有其他选择。

请注意,这绝不是对Sonar的指责。 但是,我确实认为人们应该选择一套他们认为重要的规则来应用,而不是采用默认配置。 我发现使用默认情况下启用的规则的想法有点天真。 您的项目很有可能不是工具维护者选择标准配置时考虑的项目。

此外,我相信当您遇到未知的语言功能时,您应该了解它。 当您了解它时,可以决定是否有更好的选择。

实践中的Java并发

关于JVM中并发性的事实上的标准书是Brain Goetz编写的Java Concurrency in Practice 。 它从多个详细级别解释了并发的各个方面。 如果您在Java(或不纯的Scala)中使用任何形式的并发,请确保至少阅读本书的前三章,以对问题有一个较高的了解。

翻译自: https://www.javacodegeeks.com/2014/08/javas-volatile-modifier-2.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362859.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

webpack常用loader和plugin及打包速度优化

优化 或 也可以用: 备用: 慎用的配置,用的不好会增加打包时间: 代码丑化插件: 更多专业前端知识,请上 【猿2048】www.mk2048.com

nvl 函数

nvl(oie.is_eval,N) <> Y 理解成 oie.is_eval <> Y 转载于:https://www.cnblogs.com/wangchuanfu/p/10818274.html

在自定义HttpHandler中如何使用Session

今天我写了一段程序在HttpHandler中使用Session。结果Session对象报错&#xff0c;“未将对象引用设置到对象的实例”&#xff0c;我郁闷半天&#xff0c;不知道怎么回事。结果我google了一下&#xff0c;原来也有人碰到过这种情况哦。呵呵。网上也有很多人说出了这些问题。解决…

SSH登录太慢(等很久才提示输入密码)的问题

SSH登录太慢(等很久才提示输入密码)的问题 SSH 登录太慢可能是 DNS 解析的问题&#xff0c;默认配置下 sshd 初次接受 ssh 客户端连接的时候会自动反向解析客户端 IP 以得到 ssh 客户端的域名或主机名。 如果这个时候 DNS 的反向解析不正确&#xff0c;sshd 就会等到 DNS 解析超…

开发Eclipse插件

最近&#xff0c;我开始与团队合作开发Eclipse插件。 团队开发了一个很棒的插件&#xff0c;可以实现预期的目的。 因此&#xff0c;我签出了源并尝试构建它。 项目源包含所有必需的库&#xff0c;并且只能在Eclipse中构建。 在当今不断交付的世界中&#xff0c;这是一个主要障…

react-native 热更新react-native-pushy集成遇到的问题

主要步骤按官方文档实现&#xff0c;这里只记录遇到的一些小坑 官方文档 run-android时NDK报错 前提是NDK已安装并且环境变量已设置 根据报错提示在 android/local.properties文件里加入ndk.dir~/Library/Android/android-ndk-r10e //这里改成你自己的ndk路径 cxxbridge找…

[转]在资源管理器中使鼠标右键增加一个命令,运行cmd,同时使得当前路径为资源管理器当前的目录...

[转]在资源管理器中使鼠标右键增加一个命令&#xff0c;运行cmd&#xff0c;同时使得当前路径为资源管理器当前的目录 http://www.cnblogs.com/skywind/archive/2009/05/22/1487138.html 1,找开注册表编辑器&#xff1b; 2,找到HKEY_CLASSES_ROOT\Folder\shell&#xff1b; 3,在…

Keil5 仿真测试出现Cannot Load Flash Device Description 解决方法

1.用ST的烧录软件检测&#xff0c;可以烧录对应的Hex文件。 2.点击魔术棒&#xff0c;Debug选项卡检测芯片型号是否和当前芯片对应 3.在Flash Download选项卡中检查发现没有对应的芯片型号 4.点击Add 选项&#xff0c;选择对应的Flash类型如图&#xff1a; 添加Flash类型后&…

Spring,REST,Ajax和CORS

假设您正在为客户端开发基于JavaScript的项目&#xff0c;并且他通过其余的Web服务向服务器发出Ajax请求&#xff0c;那么您可能会遇到一些麻烦&#xff0c;尤其是如果双方都在单独的域中。 实际上&#xff0c;出于安全原因&#xff0c;未授权从一个域A到另一域B的Ajax请求。 …

位运算实现加减乘除四则运算(Java)

本文是继《一文了解有趣的位运算》的第二篇文章. 我们知道&#xff0c;计算机最基本的操作单元是字节(byte)&#xff0c;一个字节由8个位(bit)组成&#xff0c;一个位只能存储一个0或1&#xff0c;其实也就是高低电平。无论多么复杂的逻辑、庞大的数据、酷炫的界面&#xff0c;…

消息(6)——WCF,构建简单的WCF服务,MTOM编码

构建一个简单的WCF服务。以Web服务类似的步骤由IIS进行宿主服务。建立的步骤&#xff1a;1 新建3.5网站2 添加WCF服务&#xff0c;自动生成契约接口与实现&#xff0c;这里改动一下&#xff0c;添加个字串参数&#xff1a;[ServiceContract]public interface IFirstService{[Op…

Hadoop—MapReducer统计文件的单词出现的个数

1. MapReduce 统计文件的单词出现的个数 Mapper: 处理具体文本&#xff0c;发送结果 Reducer: 合并各个Mapper发送过来的结果 Job: 制定相关配置&#xff0c;框架 Mapper package cn.itcast.hadoop.mr.wordcount;import java.io.IOException;import org.apache.hadoop.io.LongW…

从框架到平台

当我将近十年前作为Java开发人员开始我的职业生涯时&#xff0c;该行业正在经历革命性的变化。 Spring框架&#xff08;于2003年发布&#xff09;Swift发展起来&#xff0c;并成为庞大的J2EE平台的严重挑战者。 经过过渡时间后&#xff0c;我很快发现自己赞成使用Spring框架而不…

关于setTimeout和setInterval的函数参数问题

今天在写验证码倒计时小demo时&#xff0c;用了如下代码&#xff1a; window.setTimeout(count(num),1000);这样直接使用将使count函数立即执行&#xff0c;并将返回值传递给setTimeout函数作为参数&#xff0c;其结果并不是真正需要的&#xff0c;所以会出现问题。 方法一 …

课堂作业2

1、动手动脑 阅读示例: EnumTest.java&#xff0c;运行它&#xff0c;分析运行结果&#xff1f;你能得到什么结论&#xff1f;你掌握了枚举类型的基本用法了吗&#xff1f; public class EnumTest {public static void main(String[] args) {Size sSize.SMALL;Size tSize.LARGE…

(转)详解Vs2008下打包安装程序的一些技巧(含win7下提权限、卸载以及安装时定向到网页)...

1、怎么使得程序窗口左上角和任务栏有图标&#xff0c;如下图所示&#xff1a; 其实这个问题不应该放到程序打包这部分讲&#xff0c;只不过对于一些初学者而言&#xff0c;在这提下也许会有很大的帮助&#xff08;想到自己刚学.net那会了&#xff0c;呵呵&#xff09;。方法之…

复合双重错误

总览 在上一篇文章中&#xff0c;我概述了为什么BigDecimal大部分时间都不是答案。 虽然可以构造double会产生错误的情况&#xff0c;但在BigDecimal遇到错误的情况下构造情况也一样容易。 BigDecimal更容易正确&#xff0c;但更容易出错。 轶事证据表明&#xff0c;初级开发人…

vue入门学习示例

鄙人一直是用angular框架的&#xff0c;所以顺便比较了一下。 1 <!DOCTYPE html>2 <html lang"en">3 <head>4 <meta charset"UTF-8">5 <title>vue实践</title>6 <script src"http://cdn.bootcss.…

项目实战报异常Exception及决绝方案

1、报LifecycleException&#xff0c;再配置一下jdk即可&#xff0c;然后再手动添加maven 解决方法&#xff1a; 然后,手动添加jar包 2、maven 项目,右键maven build启动项目的时候&#xff0c;报下面错误&#xff0c;没有在pom配置tomcat7插件 3、报找不到beans插件:更新一下项…

世界主要遥感卫星

世界主要遥感卫星QuickbirdSpot-4Spot-4法国“太阳神”1A神舟飞船神舟飞船“哈勃”望远镜RADASAT神舟飞船国际空间站国际空间站 SPOT2Shutsacn IKONOS CBERS-1JersSpot-4 “哈勃”望远镜 CBERS-1 Landsat 5美国“KH-11”侦察卫星 Spot-5 ERS Landsat 7OrbView-3 美国间谍卫星…