使对易失性字段的操作原子化

总览

易失字段的预期行为是,它们在多线程应用程序中的行为应与在单线程应用程序中的行为相同。 禁止它们表现相同的方式,但不能保证它们表现相同的方式。

Java 5.0+中的解决方案是使用AtomicXxxx类,但是这些类在内存(它们添加标头和填充),性能(它们添加引用和对其相对位置的控制很少)方面效率相对较低,并且在语法上不是易于使用。

恕我直言,一个简单的解决方案,如果可变字段能够像预期的那样起作用,那么JVM必须在AtomicFields中支持的方式是当前JMM(Java内存模型)中所禁止的,但不能保证。

为什么要使字段

volatile字段的好处是,它们在线程中可见,并且某些避免重新读取它们的优化已被禁用,因此即使您没有更改它们,也总是要再次检查当前值。

例如不挥发

Thread 2:  int a = 5;Thread 1:  a = 6;

(后来)

Thread 2: System.out.println(a); // prints 5 or 6

具有挥发性

Thread 2:  volatile int a = 5;Thread 1: a = 6;

(后来)

Thread 2: System.out.println(a); // prints 6 given enough time.

为什么不一直使用

易失的读写访问速度要慢得多。 当您写入易失性字段时,它会使整个CPU管道停顿,以确保已将数据写入缓存。 否则,即使在同一线程中,也有可能在下一次读取该值时看到一个旧值(请参阅AtomicLong.lazySet(),这样可以避免流水线停顿)

惩罚可能会慢10倍左右,您不想在每次访问时都这样做。

一个重要的限制是,即使您可能认为对字段的操作也不是原子的。 甚至比通常情况更糟,没有区别。 也就是说,它似乎可以工作很长时间甚至数年,并且由于偶然的更改(例如所使用的Java版本),甚至对象加载到内存中而突然/随机中断。 例如,在运行程序之前加载了哪些程序。

例如更新值

Thread 2:  volatile int a = 5;Thread 1:  a += 1;
Thread 2:  a += 2;

(后来)

Thread 2: System.out.println(a); // prints 6, 7 or 8 even given enough time.

这是一个问题,因为对a的读取和对a的写入是分别完成的,并且您可以获得竞争条件。 99%以上的时间它会表现出预期,但有时却不会。

你能为这个做什么?

您需要使用AtomicXxxx类。 这些将易失性字段包装为具有预期行为的操作。

Thread 2:  AtomicInteger a = new AtomicInteger(5);Thread 1:  a.incrementAndGet();
Thread 2:  a.addAndGet(2);

(后来)

Thread 2: System.out.println(a); // prints 8 given enough time.

我有什么建议?

JVM具有一种按预期方式运行的方法,唯一令人惊讶的事情是您需要使用特殊的类来执行JMM不能保证的工作。 我建议更改JMM以支持并发AtomicClasses当前提供的行为。

在每种情况下,单线程行为都是不变的。 没有看到竞争条件的多线程程序将表现相同。 区别在于,多线程程序不必查看竞争条件,而可以更改基本行为。

当前方法 建议语法 笔记
x.getAndIncrement() x ++或x + = 1
x.incrementAndGet() ++ x
x.getAndDecrment() x–或x-= 1
x.decrementAndGet() -X
x.addAndGet(y) (x + = y)
x.getAndAdd(y) ((x + = y)-y)
x.compareAndSet(e,y) (x == e?x = y,true:false) 需要添加逗号语法
在其他语言中使用。


所有基本类型(例如布尔,字节,short,int,long,float和double)都可以支持这些操作。

可以支持其他赋值运算符,例如:

当前方法 建议语法 笔记
原子乘法 x * = 2;
原子减法 x-= y;
原子分裂 x / = y;
原子模量 x%= y;
原子位移 x << = y;
原子位移 x >> = z;
原子位移 x >>> = w;
原子和 x&=〜y; 清除位
原子或 x | = z; 设置位
原子异或 x ^ = w; 翻转位

有什么风险?

这可能会破坏依赖于这些操作的代码,这些代码有时会由于竞争条件而失败。

可能无法以线程安全的方式支持更复杂的表达式。 这可能会导致令人惊讶的错误,因为代码看起来像是正常的,但事实并非如此。 永远不会比当前状态更糟。

JEP 193 –增强挥发性

有一个JEP 193将该功能添加到Java。 一个例子是:

class Usage {volatile int count;int incrementCount() {return count.volatile.incrementAndGet();}
}

恕我直言,这种方法有一些限制。

  • 语法是相当重要的变化。 更改JMM可能不需要更改Java语法,也可能不需要更改编译器。
  • 这是一种不太通用的解决方案。 支持体积+ =数量等操作可能很有用; 这些是双重类型。
  • 开发人员要了解为什么他/她应该使用此代码而不是x ++ ,这会给开发人员带来更多负担;

我不相信使用更麻烦的语法可以更清楚地了解正在发生的事情。 考虑以下示例:

volatile int a, b;a += b;

要么

a.volatile.addAndGet(b.volatile);

要么

AtomicInteger a, b;a.addAndGet(b.get());

作为行,这些操作中的哪个是原子的。 他们都不回答,但是使用Intel TSX的系统可以使这些原子化,如果您要更改这些代码行中任何一个的行为,我都可以使a + = b; 而不是发明一种新的语法,该语法在大多数情况下会做同样的事情,但是可以保证一种语法,而不能保证另一种。

结论

如果JMM保证等效的单线程操作的行为符合多线程代码的预期,则可以消除使用AtomicInteger和AtomicLong的语法和性能开销。

可以使用字节码检测将该功能添加到Java的早期版本中。

翻译自: https://www.javacodegeeks.com/2014/07/making-operations-on-volatile-fields-atomic.html

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

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

相关文章

浏览器内核总结

一般来讲&#xff0c;浏览器分为外壳部分和渲染部分。外壳部分就是用户看得见摸得到的外观和操作界面;而渲染部分则包括了浏览器内核和JS引擎&#xff0c;其中JS引擎主要负责执行javascript语言实现网页上的动作&#xff0c;而内核则负责渲染网页&#xff0c;把数据变成用户可以…

SDHelper module加密系统解密

电脑上运行了SDHelper module&#xff0c;文档修改就会被加密&#xff0c;无法在别的电脑打开&#xff0c;工作中无意中发现的方法可以避开加密 1&#xff1a;可以通过打开文档并登录你的office&#xff0c;生成分享链接出去可以避免加密 2&#xff1a;本地起一个vue的项目&…

nehe教程混合这一节需要注意的两个地方

//glDepthFunc(GL_LESS); //glEnable(GL_DEPTH_TEST);///关掉深度测试,否则没效果,原因是后画的物体通不过测试,当然也就不能混合了 glDepthRange(0.0, 1.0); glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.0, 0.0, 0.0, …

Kubernetes CRD开发模式及源码实现深入剖析-Kubernetes商业环境实战

专注于大数据及容器云核心技术解密&#xff0c;可提供全栈的大数据云原生平台咨询方案&#xff0c;请持续关注本套博客。如有任何学术交流&#xff0c;可随时联系。留言请关注《数据云技术社区》公众号。 1 CRD资源扩展 CRD 即CustomResourceDefinition&#xff0c;是 kubernet…

禁止浏览器缓存

近期在改页面的时候看到了页面中有response.setHeader("Pragma","No-cache"); 这样的语句&#xff0c;不知道是做什么的&#xff0c;经查得知原来是禁止浏览器缓存的&#xff0c;现把Html&#xff0c;Asp&#xff0c;Php&#xff0c;Jsp4种语言禁止浏览器缓…

Spring @Transactional实际如何工作?

在本文中&#xff0c;我们将深入探讨Spring事务管理。 我们将讨论Transactional在Transactional如何真正工作。 其他即将发布的帖子将包括&#xff1a; 如何使用传播和隔离等功能 主要陷阱是什么以及如何避免它们 JPA和事务管理 重要的是要注意&#xff0c;JPA本身不提供任何…

python3-开发进阶-RESTful 软件架构风格

一. 什么是RESTful REST与技术无关&#xff0c;代表的是一种软件架构风格&#xff0c;REST是Representational State Transfer的简称&#xff0c;中文翻译为“表征状态转移”REST从资源的角度类审视整个网络&#xff0c;它将分布在网络中某个节点的资源通过URL进行标识&#x…

mysql卸载重装总是卡在starting server这一选项

因为自己不小心把msyql给下载了&#xff0c;重装了一个5.7版本的可是在安装时卡在starting server这一部分&#xff0c;运行不下去。重写卸载重装仍然不成功&#xff0c;还是卡在starting server.无法继续下面的安装&#xff0c;查看日志也没有报错信息。 问题分析&#xff1a;…

两款开源Web功能测试工具

参考自&#xff1a;http://www.ibm.com/developerworks/cn/web/wa-aj-testing/twill:官网&#xff1a;http://twill.idyll.org/安装&#xff1a;easy_install twill运行&#xff1a;twill-sh文档&#xff1a;http://twill.idyll.org/windmill安装&#xff1a;easy_install wind…

箭头函数与普通函数的区别

箭头函数&#xff1a; let fun () > {console.log(lalalala); } 普通函数&#xff1a; function fun() {console.log(lalla); } 箭头函数相当于匿名函数&#xff0c;并且简化了函数定义。箭头函数有两种格式&#xff0c;一种只包含一个表达式&#xff0c;连{ ... }和return…

前端基础-HTML标记语言

阅读目录 一、 HTML标签与文档结构二、 HTML标签详细语法与注意点三、 HTML中标签分类四、 HTML注释 一、 HTML标签与文档结构 HTML作为一门标记语言&#xff0c;是通过各种各样的标签来标记网页内容的。我们学习HTML主要就是学习的HTML标签。 那什么是标签呢&#xff1f; #…

cf1199解题报告

目录 cf1199解题报告ABCDEFcf1199解题报告 发一波水题。 A 模拟 #include <bits/stdc.h> #define ll long long using namespace std; const int _1e67; int n,x,y,a[_]; int main() {scanf("%d%d%d",&n,&x,&y);for(int i1;i<n;i) scanf("…

带有Gradle的Docker容器分为4个步骤

您是否需要通过Java Web应用程序创建Docker映像&#xff1f; 您在使用Gradle吗&#xff1f; 如果是这样&#xff0c;那么您距Docker nivana仅4步之遥。 对于此示例&#xff0c;我将使用一个简单的Spring Boot应用程序。 您可以在我的名为galoshe的Github存储库中找到所有源代码…

ImagesSprite V1.1.1 Beta发布

ImagesSprite v 1.1 发布后有网友提出样式显示了&#xff0c;但不能复制&#xff0c;现做调整如下&#xff08;20090804&#xff09;&#xff1a; 1.修正主界面下方css样式不能复制。 2.修正生成时透明色没有保存。【下载ImagesSprite V1.1.1 Beta】- 点击:4次转载于:https://w…

使用Spark构建简单的RESTful API

免责声明 &#xff1a;这篇文章是关于名为Spark的Java微型Web框架的&#xff0c;而不是关于数据处理引擎Apache Spark的 。 在此博客文章中&#xff0c;我们将看到如何使用Spark构建简单的Web服务。 如免责声明中所述&#xff0c;Spark是受Ruby框架Sinatra启发的Java微型Web框…

cf1206解题报告

目录 cf1206解题报告ABCDE&#xff0c;Fcf1206解题报告 A 模拟 #include <bits/stdc.h> using namespace std; int n,m,a[1010],b[12910]; int dsr[1111]; int main() {scanf("%d",&n);for(int i1;i<n;i) scanf("%d",&a[i]),dsr[a[i]]1;s…

canvas时钟

<!DOCTYPE html><html><head lang"en"><meta charset"UTF-8"><title></title></head><body><canvas id"canvas" width"500" height"500">您的浏览器不支持&#xff…

第七周

这个作业属于哪个课程C语言程序设计 &#xff08;第三版&#xff09;这个作业要求在哪里2019春季第七周作业我的课程目标学习指针的运用这个作业在哪个具体方面帮助我实现目标这个作业让我知道了指针实用性参考文献无一、2019春第七周作业&#xff08;基础题&#xff09; 7-2 自…

很久没来了,嘿嘿 问候一下大家,O(∩_∩)O哈哈~

很久没来了&#xff0c;嘿嘿。发现上次发帖正好是一个月以前哦&#xff0c;嘿嘿。最近职位火热招聘&#xff0c;有意向的快联系哦&#xff0c;嘿嘿1. BI Technical PM BI Technical PM Job Location: Redmond Oversea education or working background. 2 …

Java EE 8 –为更多设备提供更多应用程序

如果我不喜欢夏天的一件事&#xff0c;那就是事实是没有太多要分享或谈论的新闻。 谁决定将Java Day Tokyo置于这一年的无聊时间里&#xff0c;谁干得不错&#xff0c;就给我一个机会撰写有关新的和即将到来的Java EE 8规范的博客文章&#xff0c;其中包含了更多的思想和建议。…