Java中的Volatile如何工作? Java中的volatile关键字示例

如何在Java中使用Volatile关键字

在Java采访中,什么是volatile变量以及何时在Java中使用volatile变量是Java 采访中一个著名的多线程采访问题 。 尽管许多程序员都知道什么是volatile变量,但是他们在第二部分上失败了,即在Java中何处使用volatile变量,因为对Java的volatile缺乏清晰的认识和动手并不常见。 在本教程中,我们将通过提供Java中volatile变量的简单示例并讨论何时在Java中使用volatile变量来解决这一差距。 无论如何,Java中的volatile关键字用作Java编译器和Thread的指示符,它们不缓存此变量的值,而始终从主内存读取它。 因此,如果您想共享实现中原子的读写操作所涉及的任何变量,例如,以intboolean变量进行读写,则可以将它们声明为volatile变量。

从Java 5以及主要的变化(如自动装箱,枚举,泛型和变量参数)开始,Java在Java内存模型(JMM)中引入了一些更改,从而保证了从一个线程到另一个线程所做更改的可见性,也称为“事前发生”,可以解决一个线程中发生的内存写入问题可以“泄漏”并被另一个线程看到。

Java volatile关键字不能与方法或类一起使用,而只能与变量一起使用。 Java volatile关键字还保证可见性和顺序,在Java 5对任何volatile变量的写操作发生在对volatile变量的任何读取之前。 顺便说一下,使用volatile关键字还可以防止编译器或JVM对代码重新排序或使它们脱离同步障碍。

为了了解Java中volatile关键字的示例,让我们回到Java中的Singleton模式,并查看在Singleton中使用Volatile且在Java中不使用volatile关键字的情况下, 经过双重检查的锁定 。

/*** Java program to demonstrate where to use Volatile keyword in Java.* In this example Singleton Instance is declared as volatile variable to ensure* every thread see updated value for _instance.* * @author Javin Paul*/
public class Singleton{
private static volatile Singleton _instance; //volatile variable public static Singleton getInstance(){if(_instance == null){synchronized(Singleton.class){if(_instance == null)_instance = new Singleton();}}return _instance;}

如果仔细看一下代码,您将能够发现:

1)我们只创建一次实例

2)我们在第一个请求到来时懒洋洋地创建实例。

如果我们不使_instance变量可变为正在创建Singleton实例的线程无法通信其他线程,则该实例已经创建,直到它从Singleton块中出来,因此,如果线程A正在创建Singleton实例,并且创建丢失CPU之后,所有其他线程将无法看到_instance值不为null,他们将认为_instance值仍为null 。

为什么? 因为读取器线程未执行任何锁定,并且直到写入器线程脱离同步块,否则内存将不同步,并且_instance值也不会在主内存中更新。 使用Java中的Volatile关键字,此问题由Java自己处理,并且此类更新将在所有阅读器线程中可见。

因此,在摘要中,除了Java中的synced关键字外,volatile关键字还用于在线程之间传递内存的内容。

让我们看一下Java中volatile关键字的另一个示例

在编写游戏的大部分时间中,我们使用变量bExit来检查用户是否按下了退出按钮,该变量的值在事件线程中进行了更新,并在游戏线程中进行了检查,因此,如果我们不对此变量使用volatile关键字,如果尚未在Java中同步,游戏线程可能会错过事件处理程序线程的更新。 Java中的volatile关键字保证了volatile变量的值将始终从主内存中读取,并且Java Memory模型中的“ before-before”关系将确保将内存内容传递给不同的线程。

private boolean bExit;while(!bExit) {checkUserPosition();updateUserPosition();}

在此代码示例中,一个线程(游戏线程)可以缓存“ bExit ”的值,而不是每次都在其他线程(事件处理程序线程)之间更改该值时从主内存中获取它; 此线程将不可见。 在Java中将布尔变量“ bExit ”设置为volatile可以确保不会发生这种情况。

何时在Java中使用Volatile变量

学习volatile关键字最重要的事情之一就是了解何时在Java中使用volatile变量。 许多程序员都知道什么是volatile变量以及它如何工作,但他们从未真正将volatile用于任何实际目的。 这是几个示例,以演示何时在Java中使用Volatile关键字:

1)如果要自动读写long和double变量,可以使用Volatile变量。 long和double都是64位数据类型,默认情况下,long和double的写入与原子和平台无关。 许多平台在long和double变量2步中执行写操作,每步写32位,因此,线程可能会从两次不同的写操作中看到32位。 您可以通过在Java中将long和double变量变为volatile来避免此问题。

2)在某些情况下,例如Visibility,可变变量可以用作Java中实现同步的替代方法。 使用volatile变量,可以确保一旦写入操作完成,所有读取器线程都将看到volatile变量的更新值,而没有volatile关键字,则不同的读取器线程可能会看到不同的值。

3)volatile变量可用于通知编译器特定字段将被多个线程访问,这将阻止编译器进行任何重排序或任何类型的优化,而这在多线程环境中是不希望的。 如果没有易失性变量,编译器可以重新排序代码,自由地缓存易失性变量的值,而不是始终从主内存中读取。 像下面的示例一样,如果没有volatile变量,可能会导致无限循环

private boolean isActive = thread;
public void printMessage(){while(isActive){System.out.println("Thread is Active");}
}

如果没有volatile修饰符 ,则不能保证一个线程从另一线程看到isActive的更新值。 编译器还可以自由缓存isActive的值,而不必在每次迭代中从主内存中读取它。 通过将isActive为volatile变量,可以避免这些问题。

4)可以使用volatile变量的另一个地方是将双重检查锁定固定为Singleton模式。 正如我们在“ 为什么要使用Enum作为Singleton中讨论”中所讨论的那样 ,在Java 1.4环境中,再次检查锁定已被破坏。

Java中Volatile关键字的要点

1. Java中的volatile关键字仅适用于变量,并且将volatile关键字与类和方法一起使用是非法的。

2. Java中的volatile关键字保证volatile变量的值始终从主内存中读取,而不是从Thread的本地缓存中读取。

3.在Java中,使用Java volatile关键字声明的所有变量(包括long和double变量)的读写操作都是原子的。

4.在Java中对变量使用volatile关键字可降低内存一致性错误的风险,因为在Java中对volatile变量的任何写入都会与该变量的后续读取建立先发生后关系。

5.从Java 5到volatile变量的更改始终对其他线程可见。 而且,这还意味着,当线程在Java中读取volatile变量时,它不仅会看到volatile变量的最新更改,还会看到导致更改的代码的副作用。

6.读和写是原子的,因为即使不在Java中使用volatile关键字,引用变量也适用于大多数原始变量(除了long和double以外的所有类型)。

7.对Java中的volatile变量的访问永远不会有阻塞的机会,因为我们只进行简单的读或写操作,因此与同步块不同,我们永远不会保持任何锁或等待任何锁 。

8.作为对象引用的Java volatile变量可以为null。

9. Java volatile关键字不是原子的,它的普遍误解是在声明volatile ++将是原子的之后,要使操作原子化,您仍然需要确保使用Java中的同步方法或块进行独占访问。

10.如果一个变量没有在多个线程之间共享,则不需要对该变量使用volatile关键字。

Java中sync和volatile关键字之间的区别

可变和同步之间的区别是在多线程和并发访问中提出的另一个流行的Java核心问题 。 请记住,volatile不能替代synced关键字,但在某些情况下可以用作替代。 这是Java中volatile和sync关键字之间的一些区别。

1. Java中的volatile关键字是字段修饰符,而sync则修改代码块和方法。

2.同步获取并释放对监视器的Java volatile关键字的锁定,不需要这样做。

3.在同步的情况下,可以阻止Java中的线程等待任何监视器,而Java中的volatile关键字则不会。

4.同步方法比Java中的volatile关键字对性能的影响更大。

5.由于在Java中volatile关键字仅同步一个可变的螺纹存储器和“之间的值main ”存储器而同步进行同步线程存储器和“之间的所有变量的值main ”存储器和锁定和释放的监视器来引导。 由于这个原因,Java中的synced关键字可能比volatile具有更多的开销。

6.您无法在null对象上同步,但是Java中的volatile变量可能为null。

7.在Java 5中,写入volatile字段具有与监视器发行版相同的存储效果,而从volatile字段读取具有与监视器获取相同的存储效果。

简而言之,Java中的volatile关键字不能替代同步块或方法,但是在某些情况下非常方便,并且可以节省Java中使用同步所带来的性能开销。 如果您想了解更多有关volatile的知识,我还建议您在此处仔细阅读有关Java内存模型的常见问题解答,以很好地解释操作之前发生的事情。

翻译自: https://www.javacodegeeks.com/2018/03/volatile-java-works-example-volatile-keyword-java.html

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

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

相关文章

Java线程的调度及线程的优先级

调度策略 Java的调度方法 同优先级线程组成先进先出队列(先到先服务),使用时间片策略。 对高优先级,使用优先调度的抢占式策略。 线程的优先级等级 Thread.MAX_PRIORITY:10 Thread.MIN _PRIORITY:1 Threa…

Spring Boot 2应用程序和OAuth 2 –传统方法

这篇文章是3个系列文章中的第二部分,探讨了如何为基于Spring Boot 2的应用程序启用OSO2提供程序SSO。 3个帖子是: 1. 引导兼容OpenID Connect的OAuth2授权服务器/ OpenID提供程序的方法 2.与OAuth2授权服务器/ OpenID提供程序集成的旧版Spring Boot / …

Java多线程(2)--Thread类继承和Runnable接口创建线程

Java语言的JVM允许程序运行多个线程,它通过java.lang.Thread类来体现。 Thread类的特性 每个线程都是通过某个特定Thread对象的run()方法来完成操作的,经常把run()方法的主体称为线程体,通过该Thread对象的start()方法来启动这个线程&#x…

matlab在电磁场与电磁波中的应用,matlab在电磁场与电磁波学习中的应用.docx

matlab在电磁场与电磁波学习中的应用.docx MATLAB在电磁场与电磁波学习中的应用裴逸菲(燕京理工学院信息科学与技术学院,河北廊坊065201)摘要针对电磁场与电磁波在大学课程中的理论性强、概念抽象的特点,在学习中引入MATLAB软件,利用MATLAB的…

Java多线程(3)--线程的生命周期

JDK中用Thread.State类定义了线程的五种状态 要想实现多线程,必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程,在它的一个完整的生命周期中通常要经历如下的五种状态: ①新建: 当一个Thread类或…

m序列自相关matlab代码,m序列的输出及其自相关序列

【例10-2】 设m序列的生成多项式为g(x)1x^3x^4,求:(1)m序列的输出及其自相关序列;(2)脉冲波形成为矩形脉冲p(t){1 0≤t≤Tc 画出m序列信号的自相关函数;{0 其它 ,(3)设脉冲波形为升余弦函数(滚降系数a0),画…

JDK 10:从Java访问Java应用程序的进程ID

StackOverflow.com上一个普遍的问题是:“ Java程序如何获得自己的进程ID? 与该问题相关的几个答案包括解析ManagementFactory返回的String 。 getRuntimeMXBean() 。 getName() [但是可以提供“任意字符串”…

spring常见面试问题_Spring面试问题

spring常见面试问题另外,请查看我们最新的文章69Spring面试问题与解答–最终清单 。 1)什么是春天? 回答: Spring是控件和面向方面的容器框架的轻量级反转。 2)解释春天? 回答: 轻巧&#x…

matlab谱系聚类图,如何看懂SPSS聚类分析的树状图/谱系图?

原创: 数据小兵 SPSS统计训练营SPSS聚类分析提供两种类别图形的输出,第一种是软件默认的“冰柱图”,形状类似于冬天屋檐上垂下的冰柱,因此得名。第二种是“树状图”,在新版本软件中也称谱系图,像一个横着生…

Java常用类(1)--字符串相关类String、StringBuffer、StringBuilder全面知识

文章目录String类StringBuffer类StringBuilder类String:不可变的字符序列;底层使用char[]存储 StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储 StringBuilder:可变的字符序…

hybbs接口php,HYBBS

#HYBBS官方地址: http://bbs.hyyyp.com论坛基于HYPHP框架开发MVC结构支持HOOK机制PDO操作SQL,支持众多数据库论坛特性服务器环境要求:支持子目录安装论坛PHP 5.3 包括5.3 , 5.3以上环境Apache || Nginx || IIS需要开启伪静态,否则无法安装~!数据库支持 : MYSQL , MSSQL ,Oracle…

Java常用类(2)--日期时间相关类Date、Calendar、LocalDateTime、Instant全面

文章目录java.lang.System类java.util.Date类java.sql.Date类java.text.SimpleDateFormat类java.util.Calendar(日历)类java.time类java.time.Instant类java.time.format.DateTimeFormatter 类其它APIjava.lang.System类 System类提供的public static long currentTimeMillis(…

apache camel_Apache Camel简介

apache camelApache Camel是著名的企业集成模式的开源实现。 Camel是一个路由和中介引擎,可帮助开发人员以各种特定于域的语言(DSL)(例如Java,Spring / XML,scala等)创建路由和中介规则。 骆驼…

Angular5 JWT身份验证(Spring Boot安全性)

欢迎使用带有Spring Security的angular5 jwt身份验证。在本教程中,我们将在一个angular5单页应用程序中使用jwt身份验证创建一个完整的堆栈应用程序,该应用程序具有由spring boot支持并集成了spring security的后备服务器。带有集成了HttpInterceptor的示…

Java常用类(4)--System类

System类代表系统,系统级的很多属性和控制方法都放置在该类的内部,该类位于java.lang包。 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,可以…

Java常用类(5)--不可变的任意精度BigInteger、BigDecimal类

文章目录BigInteger类BigDecimal类BigInteger类 Integer类作为int的包装类,能存储的最大整型值为2^31-1,Long类也是有限的, 最大为2^63-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类 都无能为力。 java.math包的…

Java枚举类(1)--枚举类的定义、方法使用和接口实现

文章目录枚举类的理解枚举类的定义Enum类的主要方法枚举类实现接口枚举类的理解 当类的对象只有有限个,且确定的,称此类为枚举类。 当需要定义一组常量时,强烈建议使用枚举类。 如果枚举类中只有一个对象,则可以作为单例模式的…

java备忘录_Java 8备忘单中的可选

java备忘录Java 8 java.util.Optional<T>是scala.Option[T]和Data.Maybe在Haskell中的较差表亲。 但这并不意味着它没有用。 如果您不熟悉此概念&#xff0c;请将Optional想象为可能包含或不包含某些值的容器。 就像Java中的所有引用都可以指向某个对象或为null &#xf…

IDEA中注解注释快捷键及模板

前些天发现了十分不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;没有广告&#xff0c;分享给大家&#xff0c;大家可以自行看看。&#xff08;点击跳转人工智能学习资料&#xff09; 文章目录单行注释多行注释文档注释(块注释)方法说明注解自动注…

让别人和自己看懂自己的程序代码?一文掌握Java单行多行、文档注释以及注解(Annotation)超详细的理解使用,IDEA注释注解快捷键和模板,提高程序代码更有可读性

文章目录单行和多行注释文档注释&#xff08;Java特有&#xff09;Annotation(注解)的理解常见的Annotation示例IDEA注释注解快捷键及模板自定义 AnnotationJDK 中的元注解单行和多行注释 注释的内容不参与编译&#xff0c;即编译以后的.class的字节码文件中不包含注释的内容。…