ajax 示例_通过示例了解挥发

ajax 示例

未来的波动 我们已经花了几个月的时间来稳定Plumbr中的锁定检测功能 。 在此期间,我们遇到了许多棘手的并发问题。 许多问题是独特的,但是一种特殊类型的问题一直反复出现。

您可能已经猜到了–滥用volatile关键字。 我们已经发现并解决了许多问题,其中大量使用volatile使应用程序的任意部分变慢,延长了锁定保持时间,最终使JVM屈服。 反之亦然-授予过于宽松的访问策略会引发一些令人讨厌的并发问题。

我想每个Java开发人员都会回想起该语言的第一步。 使用手册和教程的日子和日子。 这些教程都有关键字列表,其中volatile是最可怕的关键字之一。 随着时间的流逝,越来越多的代码不需要使用此关键字,我们很多人都忘记了volatile的存在。 直到生产系统开始以无法预测的方式破坏数据或死亡。 调试这种情况迫使我们中的一些人真正理解了这个概念。 但是我敢打赌,这并不是一个令人愉快的课程,因此也许我可以通过一个简单的例子来阐明一些概念,从而节省一些时间。

挥发作用的例子

该示例模拟了一个银行办公室。 银行办公室的类型,您可以在该办公室中从售票机中选择队列编号,然后在您前面的队列得到处理后等待邀请。 为了模拟这样的办公室,我们创建了以下示例,该示例由两个线程组成。

这两个线程中的第一个被实现为CustomerInLine。 这是一个线程,除了等待NEXT_IN_LINE中的值与客户的票证匹配外,什么也不做。 票号被硬编码为#4。 时间到时( NEXT_IN_LINE> = 4),线程宣布等待已结束并结束。 这模拟了有一些客户在排队的到达办公室的客户。

排队实现在Queue类中,该类运行一个循环,该循环调用下一个客户,然后通过为每个客户Hibernate200ms来模拟与该客户的工作。 呼叫下一个客户后,存储在类变量NEXT_IN_LINE中的值将增加1。

public class Volatility {static int NEXT_IN_LINE = 0;public static void main(String[] args) throws Exception {new CustomerInLine().start();new Queue().start();}static class CustomerInLine extends Thread {@Overridepublic void run() {while (true) {if (NEXT_IN_LINE >= 4) {break;}}System.out.format("Great, finally #%d was called, now it is my turn\n",NEXT_IN_LINE);}}static class Queue extends Thread {@Overridepublic void run() {while (NEXT_IN_LINE < 11) {System.out.format("Calling for the customer #%d\n", NEXT_IN_LINE++);try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}}}
}

因此,运行此简单程序时,您可能希望该程序的输出类似于以下内容:

Calling for the customer #1
Calling for the customer #2
Calling for the customer #3
Calling for the customer #4
Great, finally #4 was called, now it is my turn
Calling for the customer #5
Calling for the customer #6
Calling for the customer #7
Calling for the customer #8
Calling for the customer #9
Calling for the customer #10

看来,这个假设是错误的。 取而代之的是,您将看到通过10个客户的列表进行的队列处理,并且不幸的线程模拟了4号客户,从不提醒它已经看到邀请。 发生了什么,为什么客户仍然坐在那里无休止地等待着呢?

分析结果

您在此处面临的是将JIT优化应用于代码,该代码将对NEXT_IN_LINE变量的访问进行缓存。 两个线程都有自己的本地副本,并且CustomerInLine线程从不看到Queue实际增加了线程的值。 如果现在您认为这是JVM中的一种可怕的错误,那么您就不完全正确了-允许编译器这样做以避免每次都重新读取该值。 因此,您可以提高性能,但要付出代价–如果其他线程更改状态,则缓存副本的线程将不知道该状态,并使用过时的值进行操作。

对于volatile正是这种情况。 有了此关键字,编译器将被警告特定状态是易失的,并且每次执行循环时,代码都被强制重新读取该值。 有了这些知识,我们就可以进行简单的修复-只需将NEXT_IN_LINE的声明更改为以下内容,您的客户就不会永远坐在队列中:

static volatile int NEXT_IN_LINE = 0;

对于那些只了解volatile用例而感到满意的人,您将很高兴。 只是要知道附加的成本–当您开始声明所有内容都是易失性时,您正在迫使CPU忽略本地缓存并直接进入主内存,从而减慢了代码的速度并阻塞了内存总线。

引擎盖下易挥发

对于那些希望详细了解该问题的人,请和我在一起。 要查看底层发生了什么,让我们打开调试以查看JIT从字节码生成的汇编代码。 通过指定以下JVM选项可以实现此目的:

-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly

在启用和禁用volatile的情况下启用这些选项的情况下运行程序,可以为我们提供以下重要见解:

运行不带volatile关键字的代码,表明我们在指令0x00000001085c1c5a上可以比较两个值。 当比较失败时,我们继续从0x00000001085c1c60到0x00000001085c1c66,后者跳回到0x00000001085c1c60,并产生无限循环。

0x00000001085c1c56: mov    0x70(%r10),%r11d0x00000001085c1c5a: cmp    $0x4,%r11d0x00000001085c1c5e: jge    0x00000001085c1c68  ; OopMap{off=64};*if_icmplt; - Volatility$CustomerInLine::run@4 (line 14)0x00000001085c1c60: test   %eax,-0x1c6ac66(%rip)        # 0x0000000106957000;*if_icmplt; - Volatility$CustomerInLine::run@4 (line 14);   {poll}0x00000001085c1c66: jmp    0x00000001085c1c60  ;*getstatic NEXT_IN_LINE; - Volatility$CustomerInLine::run@0 (line 14)0x00000001085c1c68: mov    $0xffffff86,%esi

使用volatile关键字后,我们可以看到在指令0x000000010a5c1c40上我们将值加载到寄存器,在0x000000010a5c1c4a上将其与保护值4进行比较。如果比较失败,则从0x000000010a5c1c4e跳回0x000000010a5c1c40,再次为新的值加载值检查。 这确保了我们将看到NEXT_IN_LINE变量的更改后的值。

0x000000010a5c1c36: data32 nopw 0x0(%rax,%rax,1)0x000000010a5c1c40: mov    0x70(%r10),%r8d    ; OopMap{r10=Oop off=68};*if_icmplt; - Volatility$CustomerInLine::run@4 (line 14)0x000000010a5c1c44: test   %eax,-0x1c1cc4a(%rip)        # 0x00000001089a5000;   {poll}0x000000010a5c1c4a: cmp    $0x4,%r8d0x000000010a5c1c4e: jl     0x000000010a5c1c40  ;*if_icmplt; - Volatility$CustomerInLine::run@4 (line 14)0x000000010a5c1c50: mov    $0x15,%esi

现在,希望说明能使您摆脱几个讨厌的错误。

翻译自: https://www.javacodegeeks.com/2014/08/understanding-volatile-via-example.html

ajax 示例

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

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

相关文章

oracle long转为string,实现全局拦截前端传入的Long类型id转String

1遇到的问题在开发过程中存在这样一种问题&#xff0c;我们使用的id主键主要有long类型和varchar类型当主键id为long类型并且长度超过16位&#xff0c;当返回给前端时&#xff0c;前端会出现js解析的参数如果是Long类型的并且长度过大就会出现精度丢失。这就会造成后台返回的值…

springboot 多线程_redis官方推荐:SpringBoot用这个,一键多线程

Lettuce是一个可伸缩的线程安全的Redis客户端&#xff0c;提供了同步&#xff0c;异步和响应式使用方式。 如果多线程避免阻塞和事务操作(如BLPOP和MULTI / EXEC)&#xff0c;则多个线程可共享一个连接。 Lettuce使用通信使用netty。 支持先进的Redis功能&#xff0c;如Sentine…

oracle查询最高一条记录,oracle 查询已有记录,上一条记录,下一条记录

oracle可以使用 lead、lag 函数来查询已有记录的下一条、上一条记录。表结构如下&#xff1a;如要查询Staffno是6-1102的前一条记录select * from staff where staff_no(select c.p from (select staff_no,lag(staff_no,1,0) over (order by staff_no) as p from staff) c wh…

使用Maven进行增量构建

这是2020年&#xff0c;如果您要启动任何新的基于Java的项目&#xff0c;则应优先选择gradle&#xff0c;但由于某些原因&#xff0c;如果您仍然对Maven感兴趣&#xff0c;那么您可能会发现这篇文章有用。 Maven Java / scala编译器插件对增量编译提供了不错的支持&#xff0c…

夏末浅笑_2014年夏末大Java新闻

夏末浅笑正如即将到来的JavaOne那样 &#xff0c;最近在Java社区中已经有很多重大新闻。 这篇文章简要地引用了其中的三个项目&#xff08;Java SE 8更新&#xff0c;Java SE 9和Java EE 8&#xff09;&#xff0c;并对我发现是我在类路径/类加载器问题上见过的更清晰的文章之一…

php删除菜单栏,如何删除WordPress站点健康状态面板和菜单项

下面由WordPress教程栏目给大家介绍删除WordPress站点健康状态面板和菜单项的方法&#xff0c;希望对需要的朋友有所帮助&#xff01;删除 WordPress 站点健康状态面板和菜单项WordPress站点健康功能始于 5.2 版&#xff0c;如不想显示这玩意&#xff0c;可以使用本文的方法删除…

colspan会影响内部单元格宽度失效_电感失效分析

电感失效分析01电感的作用我们通常所说的电感指的是电感器件&#xff0c;它是用绝缘导线(例如漆包线,沙包线等)绕制而成的电磁感应元件。在电路中&#xff0c;当电流流过导体时&#xff0c;会产生电磁场&#xff0c;电磁场的大小除以电流的大小就是电感。电感是衡量线圈产生电磁…

linux清空redis命令,使用Linux管道批量删除Redis的key

------------------------------------------------------Redis并没有提供批量删除记录的方法&#xff0c;这有时候很不方便&#xff0c;特别是重新初始化数据的时候。一般有两种做法&#xff1a;如果业务场景明确&#xff0c;可以通过DBID进行区分&#xff0c;Redis默认的DBID…

ZeptoN正在将程序放入Java

1.简介 Java编程语言或“ Java”于1995年引入。然而&#xff0c;在近25年的时间里&#xff0c;它增加了最初不是核心语言所具有的功能。 此类功能包括枚举&#xff0c;泛型&#xff0c;对基本C样式功能开关语句的许多增强&#xff0c;断言等。 Java是一种编程语言&#xff0c;随…

深入理解python面向对象_转:Python3 面向对象,较为深入的两个理解

一&#xff0c;1. 类的声明和创建对于 Python 函数来说&#xff0c;声明与定义类没什么区别&#xff0c;因为他们是同时进行的&#xff0c;定义(类体)紧跟在声明(含 class 关键字的头行[header line])和可选(但总是推荐使用)的文档字符串后面。同时&#xff0c;所有的方法也必须…

linux循环脚本while循环,Shell脚本while、until循环语句简明教程

一、while循环while循环用于不断执行一系列命令&#xff0c;也用于从输入文件中读取数据&#xff1b;命令通常为测试条件。其格式为&#xff1a;while 命令docommand1command2...commandNdone命令执行完毕&#xff0c;控制返回循环顶部&#xff0c;从头开始直至测试条件为假。以…

分披萨问题_比萨问题–建造者与装饰者

分披萨问题问题陈述 我们需要为一家披萨公司构建软件&#xff0c;该公司想要准备不同类型的披萨&#xff0c;例如鸡肉披萨&#xff0c;扁平面包&#xff0c;意大利辣香肠披萨和特制奶酪&#xff0c;并在上面放些配料。 让我们尝试看看哪种设计模式适合该问题说明以及在哪种情况…

用python随机生成5000个网址_使用Python脚本生成随机IP的简单方法

需求在某应用中&#xff0c;需要根据一定的规则生成随机的IP地址&#xff0c;规则类似于192.168.11.0/24这样的CIDR形式给出。实现经过艰苦卓绝的调试&#xff0c;下面的代码是可以用的&#xff1a;RANDOM_IP_POOL[192.168.10.222/0]def __get_random_ip():str_ip RANDOM_IP_P…

linux应用程序安装PPT免费序,linux下应用程序安装的总结

linux下应用程序安装的总结上一篇 / 下一篇 2009-04-20 14:45:37 / 个人分类&#xff1a;技术我解查看( 203 ) / 评论( 0 ) / 评分( 0 / 0 )一、常用的Linux应用软件的安装包有2种&#xff1a;1. tar包&#xff0c;如software-1.2.3-1.tar.gz。它是使用linux系统的打包工具tar打…

Quarkus入门

Quarkus – 一个为OpenJDK HotSpot和GraalVM量身定制的Kubernetes本机Java堆栈&#xff0c;它是从最佳Java库和标准中精制而成的。 –是一个容器优先的框架&#xff0c;针对快速启动时间和低内存消耗进行了优化。 该框架基于许多流行的Java库构建&#xff0c;并且为构建标准RES…

vmware6.5.2序列号_教你如何查询苹果序列号,查询是否为官换机、激活时间等

如何查询你刚买的苹果设备是否为官换机&#xff1f;或想知道它的激活日期&#xff1f;保修时间&#xff1f;那么赶紧收藏本篇教程吧&#xff01;众所周知&#xff0c;在苹果官网查询苹果设备&#xff0c;是查询不到具体的信息&#xff08;比如激活日期、保修日期、是否为官换机…

linux 几个文件夹作用,linux下每一个文件夹的作用.docx

目录结构及主要内容“/"根冃录部分有以F子冃录&#xff1a;/usr 口录包含所有的命令、程序库、文档和英它文件。这些文件在正常操作中不会被改变的。这个目录也包含你的Linux 发行版本的主要的应用程序&#xff0c;辔如&#xff0c;Netscape0/var目录包含在1E常操作中被改…

参数化测试 junit_JUnit中的参数化测试运行器

参数化测试 junit我们都有书面的单元测试&#xff0c;其中在一个测试中针对不同的可能的输入输出组合进行测试。 让我们以一个简单的斐波那契数列示例为例&#xff0c;看看它是如何完成的。 以下代码针对提到的元素数量计算斐波那契数列&#xff1a; import java.math.BigInt…

python中dataframe合并列名日期到季度_python – 如何在特定日期范围内的pandas列DataFrame中对某些值求和...

我有一个大型的DataFrame,看起来像这样&#xff1a;df UPC Unit_Sales Price Price_Change Date0 22 15 1.99 NaN 2017-10-101 22 7 2.19 True 2017-10-122 22 6 2.19 NaN 2017-10-133 22 7 1.99 True 2017-10-164 22 4 1.99 NaN 2017-10-175 35 15 3.99 NaN 2017-10-096 35 17…

linux环境变量自动配置,Linux进入系统时自动配置 环境变量的要领

用Export命令能够配置环境变量&#xff0c;但是假如每回进入系统之后都要重新配置一遍环境变量就很烦人。Linux给大众提供了自动配置环境变量的要领&#xff0c;那就是修改.bashrc 文件。 通常说来&#xff0c;有两个文件能够提供这种“进入系统时自动配置”的功能&#xff0c;…