volatile关键字的作用-适用场景

volatile在Java并发编程中常用于保持内存可见性和防止指令重排序。内存可见性(Memory Visibility):所有线程都能看到共享内存的最新状态;防止指令重排:在基于偏序关系的Happens-Before内存模型中,指令重排技术大大提高了程序执行效率,但同时也引入了一些问题。

volatile保持内存可见性的特殊规则:read、load、use动作必须连续出现;assign、store、write动作必须连续出现;每次读取前必须先从主内存刷新最新的值;每次写入后必须立即同步回主内存当中。

也就是说,volatile关键字修饰的变量看到的随时是自己的最新值。在线程1中对变量v的最新修改,对线程2是可见的。

volatile防止指令重排的策略:在每个volatile写操作的前面插入一个StoreStore屏障;在每个volatile写操作的后面插入一个StoreLoad屏障;在每个volatile读操作的后面插入一个LoadLoad屏障;在每个volatile读操作的后面插入一个LoadStore屏障。

注意:只有在Happens-Before内存模型中才会出现这样的指令重排序问题。

 

1.volatile最适用一个线程写,多个线程读的场合

   如果有多个线程并发写操作,仍然需要使用锁或者线程安全的容器或者原子变量来代替。(摘自Netty权威指南)

   疑问:如果只是赋值的原子操作,是否可以多个线程写?(答案:可以,但是一般没有这样的必要,即没有这样的应用场景)

 

最经典的使用案例:

复制代码

volatile boolean shutdownRequested;...public void shutdown() { shutdownRequested = true; }public void doWork() { while (!shutdownRequested) { // do stuff}
}

 

使用场景2:

结合使用 volatile 和 synchronized 实现 “开销较低的读-写锁”

volatile 允许多个线程执行读操作,因此当使用 volatile 保证读代码路径时,要比使用锁执行全部代码路径获得更高的共享度 —— 就像读-写操作一样。

 

public class CheesyCounter {private volatile int value;public int getValue() { return value; }public synchronized int increment() {return value++;}
}

 

或者

   private volatile long start = System.currentTimeMillis();public synchronized long get() {return start++;}

 

正确使用 volatile 变量的条件

您只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:

  • 对变量的写操作不依赖于当前值。
  • 该变量没有包含在具有其他变量的不变式中。

更多使用场景可参考:

http://www.ibm.com/developerworks/cn/java/j-jtp06197.html

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

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

相关文章

MySQL你掌握了多少?这些SQL题你能作对几道?

MySQL是工作中常用数据库,必须掌握,但小伙伴们又掌握了多少呢,今天一起来测试一下吧~ 力扣SQL ⭐组合两个表 ⭐第二高的薪水 ⭐超过经理收入的员工 ⭐查找重复的电子邮箱 ⭐从不订购的客户 ⭐大的国家 ⭐删除重复的电子邮箱 ⭐有趣的…

mybatis配置文件加注释报错怎么办?改一笔就能帮你解决

今天配置mybatis写了一个小demo,本以为顺顺利利的就完成了,没想到就报了如下错误。直接emo了。 java.lang.ExceptionInInitializerErrorat com.lm.learn.dao.UserTest.getUsers(UserTest.java:14)at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ…

第十二节:深究内核模式锁的使用场景(自动事件锁、手动事件锁、信号量、互斥锁、读写锁、动态锁)

一. 整体介绍 温馨提示:内核模式锁,在不到万不得已的情况下,不要使用它,因为代价太大了,有很多种替代方案。 内核模式锁包括: ①:事件锁 ②:信号量 ③:互斥锁 ④&#xf…

玩转Mybatis —— 一个小demo,带你快速入门Mybatis

目录 🤞Mybatis官网介绍 🤞Mybatis安装 🤞Mybatis核心配置文件 🤞构建 SqlSessionFactory 🤞获取 SqlSession 🤞通过 XML 定义已映射的 SQL 语句 🤞作用域(Scope)…

MySQL掌握的怎么样?听说这几道MySQL面试题没有几个人能答得出来

MySQL可谓是程序员必备技能,怎么检测自己掌握了多少呢,一起来测试一下吧!一共12个关卡,看看你能闯到第几关? 目录 什么是左外链接,什么是右外链接? 分页关键字是什么? Select 语句…

IIS/ASP.NET 管道

ASP.NET MVC 是建立在 ASP.NET 平台上基于 MVC 模式的 Web 应用框架,深刻理解 ASP.NET MVC 的前提是对 ASP.NET 管道式设计具有深刻的认识。由于 ASP.NET Web 应用大都寄宿于 IIS 上,将两者结合起来了解在 IIS 和 ASP.NET 管道中是如何流动的。 IIS5.x与…

【JAVA知识点每日一练】 —— 运算符的那些事

都说基础不牢地动山摇,还真是那么回事!别小看这运算符,每个语法中运算符扮演者举足轻重的角色,稍微没用对,那可就犯了大错误! 接下来跟随小梦,迈着轻松且愉快的步伐一起看看运算符的那些事吧~ 运…

ASP.NET Core管道深度剖析[共4篇]

在《管道是如何处理HTTP请求的?》中,我们对ASP.NET Core的请求处理管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的。这样一个管道由一个服务器和一个HttpApplication构成&#xff0c…

SQL为什么动不动就百行以K记?

发明SQL的初衷之一显然是为了降低人们实施数据查询计算的难度。SQL中用了不少类英语的词汇和语法,这是希望非技术人员也能掌握。确实,简单的SQL可以当作英语阅读,即使没有程序设计经验的人也能运用。 然而,面对稍稍复杂的查询计算…

深入理解happens-before和as-if-serial语义

本文大部分整理自《Java并发编程的艺术》,温故而知新,加深对基础的理解程度。下面可以和小编来一起学习下 概述 本文大部分整理自《Java并发编程的艺术》,温故而知新,加深对基础的理解程度。 指令序列的重排序 我们在编写代码…

开源SPL重新定义OLAP Server

OLAP(Online Analytical Processing)是指在线联机分析,基于数据查询计算并实时获得返回结果。日常业务中的报表、数据查询、多维分析等一切需要即时返回结果的数据查询任务都属于OLAP的范畴。对应的,行业内也有相应产品来满足这类…

平层、错层、跃层、复式、loft的区别是什么?

平层正如字面上的理解,是所有功能厅都在同一个水平面上。平时我们所见的户型,都是平层。错层室内各功能用房在不同的平面上,用2-4个台阶进行隔断。跃层是两层的住宅,在室内会设计一条楼梯连接上下两层,功能区会分开。复…

C#中集合接口关系笔记

IEnumerable IEnumerable接口是所有集合类型的祖宗接口,其作用相当于Object类型之于其它类型。如果某个类型实现了IEnumerable接口,就意味着它可以被迭代访问,也就可以称之为集合类型(可枚举); ICollecti…

C#集合类型总结和性能分析

C#集合类型概述 集合是.NET FCL(Framework Class Library)中很重要的一部分。所有的集合类都继承自IEnumerable。集合类总体可分为一下几类:关联/非关联型集合,顺序/随机访问集合,顺序/无序集合,泛型/非泛型集合,线程…

为什么TypedReference在幕后

我发现的其他用途TypedReference: C#中的“专门化”泛型(这是类型安全的)&#xff1a; static void foo<T>(ref T value) {//This is the ONLY way to treat value as int, without boxing/unboxing objectsif (value is int){ __refvalue(__makeref(value), int) 1; …

C# 中的可变参数方法(VarArgs)

首先需要明确一点&#xff1a;这里提到的可变参数方法&#xff0c;指的是具有 CallingConventions.VarArgs 调用约定的方法&#xff0c;而不是包含 params 参数的方法。可以通过MethodBase.CallingConvention 属性来获取某个方法的调用约定。 举个常见的例子来说&#xff0c;C…

Spring Boot Actuator监控关闭

可以使用如下属性:management.endpoints.enabled-by-defaultfalse * 在YAML中有特殊的含义&#xff0c;所以如果想使用include或者exclude包含所有的端点时要加上引号&#xff0c;如下示例&#xff1a; # 暴露监控端点 management:endpoints:enabled-by-default: false #关闭…

Javascript获取类名方法

函数&#xff1a; entity.getClassName function(obj) { if (obj && obj.constructor && obj.constructor.toString()) { if(obj.constructor.name) { return obj.constructor.name; } let str…

mysql把一个数据库中的数据复制到另一个数据库中的表 2个表结构相同

1。表结构相同的表&#xff0c;且在同一数据库&#xff08;如&#xff0c;table1,table2) Sql &#xff1a;insert into table1 select * from table2 (完全复制) insert into table1 select distinct * from table2(不复制重复纪录&#xff09; insert into table1 select …

!Spring Aop中四个重要概念,切点,切面,连接点,通知

一、基本概念 1. 通知&#xff1a; 就是我们编写的希望Aop时额外执行的那个方法。我们通过Aop希望我们编写的方法在目标方法执行前执行&#xff0c;或者执行后执行。 2. 切点&#xff1a;切点就是我们配置的满足我们条件的目标方法。比如我们规定&#xff1a;名字前面是select…