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位可变原子(如long s和double s)。 要写入变量,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/07/javas-volatile-modifier.html

java 挥发注解

java 挥发注解_Java的挥发性修饰符相关推荐

  1. java 挥发注解_C中的挥发性预选赛

    java 挥发注解 什么是C中的限定词? (What is Qualifiers in C?) Qualifiers in C are the keywords which are used to m ...

  2. java中有哪几种访问修饰符_Java语言中有4种访问修饰符

    转载:http://wuhaidong.iteye.com/blog/851754 Java语言中有4种访问修饰符 在Java语言中有4中访问修饰符:package(默认).private.publi ...

  3. java进阶之匿名内部类,访问修饰符,包

    文章目录 一.形式参数和返回值 二.包 1.包 2.导包 三.权限修饰符 1.权限修饰符: 2.常见的权限修饰符 四.内部类 一.形式参数和返回值 (1)形式参数: 类名:需要该类的对象 抽象类名:需 ...

  4. Java的挥发性修饰符

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

  5. java平台类成员访问修饰符_JAVA类的修饰符及访问权限

    1.类 外部类      class前的修饰符只能有public final abstrct 无(默认) :同包可见  (Eclipse中选择package) 内部类      class前的修饰符有 ...

  6. java中的权限修饰符_Java的权限修饰符的区别和用法总结

    类中的数据成员和成员函数据具有的访问权限包括:public.private.protect.friendly(包访问权限). 1.public:public表明该数据成员.成员函数是对所有用户开放的, ...

  7. java的修饰符_java默认的修饰符是什么

    默认什么都不加,就是default(不用把default写出来). 意思就是只能由跟这个类在同一个包中的类来访问,比private限制更少,但比protected限制更多.' Java访问修饰符包括p ...

  8. java 中final修饰的变量_java中final修饰符的使用方法

    本文为大家分享了java中final修饰符的使用,供大家参考,具体内容如下 1.final修饰符的用法: final可以修饰变量,被final修饰的变量被赋初始值之后,不能对它重新赋值. final可 ...

  9. java默认修饰符_java默认的修饰符是什么

    默认什么都不加,就是default(不用把default写出来). 意思就是只能由跟这个类在同一个包中的类来访问,比private限制更少,但比protected限制更多.' Java访问修饰符包括p ...

最新文章

  1. 腾讯 AI 医学进展破解“秃头”难题,登 Nature 子刊!
  2. 怎么重写MDK(KEIL)Flash烧写程序
  3. 没有 root 权限如何使用 pip?How to install python modules without root access?
  4. Chrome 90 里更好的字符串处理机制
  5. QQ浏览器怎样在首页显示优先推荐的网站
  6. python的应用领域和常用函数模块有哪些_Python模块导入区别与常用函数案例
  7. 试论述计算机辅助教学的特点,浅谈计算机辅助教学特点
  8. too many connections的一个实践
  9. 信息检索 IR 中的评价指标
  10. 思科模拟器静态路由设置,以及rip路由设置
  11. 计算机毕业设计之java+springboot基于vue的4S店车辆管理系统
  12. Android 复杂的多类型列表视图新写法:MultiType 3.0
  13. MT6755芯片资料文档
  14. 法拉利虚拟学院2010 服务器,法拉利虚拟学院
  15. Android QQ 登录接入详细介绍
  16. kali下中英文输入任意切换
  17. c3p0详细配置介绍
  18. 使用 QTLtools 进行 PCA 分析
  19. mysql怎么样修改schema_MySQL 5.6使用pt-online-schema-change在线修改大表字段长度
  20. php屏蔽地区_屏蔽指定省份访问PHP代码

热门文章

  1. 欢乐纪中某A组赛【2019.1.19】
  2. ssl2644-线段树练习1【线段树】
  3. 【c++算法刷题笔记】——洛谷2
  4. 【动态规划】数字金字塔
  5. Nacos client SDK 订阅式请求坑
  6. Hadoop入门(十六)Mapreduce的单表关联程序
  7. 选择大公司还是小公司
  8. Oracle入门(十四G)之PL / SQL中检索数据
  9. JSON Web Token (JWT),服务端信息传输安全解决方案
  10. 老师 累了,我们 泪了!