java多线程 sycophantic_Java多线程volatile和synchronized总结

volatile是轻量级的synchronized,在多处理器(多线程)开发中保证了共享变量的“可见性”。可见性表示当一个线程修改了一个共享变量时,另外一个线程能读到这个修改的值。正确的使用volatile,能比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换和调度。使用时只需要把字段声明成volatile即可。

处理器实现,有volatile变量修饰的共享变量进行写操作的时候会出现LOCK前缀指令。触发两件事情,1、将当前处理器缓存行的数据写回到系统内存。2、这个写会内存的操作会使在其他CPU里缓存了该内存地址的数据无效。

正常情况下,处理器不直接和内存进行通信,而是先将系统内存的数据读取到内部缓存(L1,L2或其他),但操作完不知道何时会写到内存。如果对声明了volatile的变量进行写操作,JVM就会向处理器发送一条LOCK前缀的指令,将这个变量所在的缓存行的数据写回到内存。但是,就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题。所有,在多处理器下,为了保证各个处理器缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己的缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置为无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据都到处理器缓存里。

volatile两个实现原则

1)在执行指令期间,声言处理器的LOCK#信号。在多处理器环境中,LOCK#信号确保在声言该信号期间,处理器可以独占任何共享内存。在老的处理器中,LOCK#信号一般锁总线,但是锁总线的开销比较大,现在的处理器,一般锁缓存。

2)一个处理器的缓存回写到内存内会导致其他处理器的缓存无效。

volatile所能保证的是可见性,不能保证Java程序的原子性。

还是以最常用的i++来说吧,包含3个步骤

1,从内存读取i当前的值

2,加1

3,把修改后的值刷新到内存

对于普通变量来说多线程下1,2之间被中断,其它线程修改了i的值,那原来已经在1,2之间被中断的线程的i的值就已经无效了,所以多线程是不安全的。

另外对于普通变量来说,步骤1并不是每次都会从内存中读取,步骤3也并不会每次都保证会立即刷新到内存。

所以这里有两个问题,可见性和原子性,viloate只能保证可见性,即步骤1每次都重新读,步骤3每次都立即刷新到主内存。但1,2之间仍然会被中断,多个线程交叉修改,所以仍然不安全。

synchronized,Java中每个对象都可以作为锁。3种形式:1、普通同步方法,锁就是当前实例对象。2、静态同步方法,锁是当前类的class对象。3、同步方法块,锁是Synchronized括号里配置的对象。

JVM基于进入和退出Monitor对象来实现方法同步和代码块同步,但是实现细节不同,代码块同步是实用monitorenter和monitorexit指令实现的,而方法同步是实用另外一种方式实现。monitorenter插入在代码块的开始位置,而monitorexit是插入在代码块结束和异常处,保证每个monitorenter必须有对应的monitorexit配对,任何一个对象都有monitor关联,当且一个monitor被持有后,就处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获取对象的锁。

Java SE1.6为了减少获取锁和释放锁的性能消耗,引入了“偏向锁”和“轻量级锁”,总共四种状态:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。

2f545a6b02488de38b2cdc004dc5d204.png

上图,主要是对象头的详细说明。

偏向锁

主要针对只有一个线程访问同步块的场景(很多情况下不存在多线程竞争,总是由同一个锁多次获得),如果是这种情况直接在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程在进入和退出同步块时不需要进行CAS操作来加锁和解锁。Word里是否存储着指向当前线程的偏向锁。如果测试成功,表示线程已经获得了锁。如果测试失败,则需要再测试一下Mark Word中偏向锁的标识是否设置成1(表示当前是偏向锁):如果没有设置,则使用CAS竞争锁;如果设置了,则尝试使用CAS将对象头的偏向锁指向当前线程。

偏向锁的撤销,等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁。

缺点是如果线程间存在锁竞争,会带来额外的锁撤销的消耗。

轻量级锁

竞争的线程不会阻塞,提高程序的响应速度,但是如果始终得不到锁竞争的线程,使用自旋会消耗CPU,适用于追求响应时间,同步块执行速度非常快。

重量级锁

线程竞争不适用自旋,不会消耗CPU,但是会线程阻塞,响应时间缓慢。适用于追求吞吐量,同步块执行速度较长。

762ddd474f10a4ce26ba919332364e46.png

上图是synchronized原理图,分享一下。

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

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

相关文章

[BOOST] BOOST::Format

cout << format( "%1% says \"%2%\" to %1%.\n" ) % "Yousen" % "Hello";这句话将在标准输出上输出“Yousen says "Hello" to Yousen.”接下来简单说明一下format的用法。估计聪明人都猜到了&#xff0c;在格式化字符…

using IDisposable

using和IDisposable是组合使用的&#xff0c;像这种一个关键字和一个接口的组合&#xff0c;在C#中很少见的&#xff0c;using这个关键字&#xff0c;也就因为IDisposable多了一个身份。其实很多人都知道IDisposable&#xff0c;有一个方法void Dispose()&#xff0c;通常是用来…

春节特惠活动┃不只是舒适,简直是享受,Google公司用的腰靠,到底有什么秘密?...

▲数据汪特别推荐点击上图进入玩酷屋之前小木推荐“德国MINICUTE人体工学腰垫”受到了大家一致的好评和争相购买。小木为什么推荐这一款原因是&#xff1a;据统计&#xff0c;我国腰椎病患者已经突破2亿人。30~40岁人群中&#xff0c;患有颈腰椎病的占比59.1%&#xff01;而且有…

linux mysql phpadmin_linux安装phpmyadmin数据库管理

安装phpmyadminyum -y install phpmyadmin //执行yum在线安装程序安装完成后&#xff0c;可在/usr/share目录下找到phpMyAdmin找到 phpMyAdmin/libraries/config.default.php文件&#xff0c;将config.default.php复制到phpmyadmin目录下&#xff0c;然后更名为config.inc.…

2012平安夜

2012平安夜&#xff0c;我的博客园开通了&#xff0c;在这里我将与他开始崭新的学习生活。

.Net单元测试方法

单元测试是一种编程测试&#xff0c;这些测试既可以使用 Visual C# 或 Visual Basic 编写&#xff0c;也可以使用 Visual C 编写并用 /clr:safe 选项进行编译。单元测试用于通过直接调用某个类的方法&#xff08;传递相应参数&#xff09;来执行其他源代码。因此&#xff0c;如…

春节特惠活动┃给孩子讲100个科学道理,不如带他做这些趣味实验!

▲数据汪特别推荐点击上图进入玩酷屋玩具和学习看似是两个对立的东西&#xff0c;孩子天性爱玩&#xff0c;家长却希望孩子能多学习。不一定非要啃课本才能汲取知识&#xff0c;有时候&#xff0c;在轻松有趣的游戏中也能学到课堂上学不到的知识。让学习变得有趣、高效——给孩…

linux java 进程监控工具_推荐4个好用的Linux监控工具

本文介绍了作者常用的 4 个 Linux 监控工具&#xff0c;希望可以帮助读者提高生产力。身为一个运维开发人员&#xff0c;如果你不知道眼下当前服务器底层操作系统中正在发生什么&#xff0c;那就有点合眼摸象了。其实&#xff0c;你可以根据相应数据做出一定的推测&#xff0c;…

html页面音乐播放器_Embed代码

播放器代码如下&#xff1a; HTML播放器样式1 代码&#xff1a; <P aligncenter> <TABLE borderColor#bc8f8f cellSpacing1 width315 border1> <TBODY> <TR> <TD><EMBED style"FILTER: invert(); WIDTH: 315px; HEIGHT: 28px" sr…

看TensorFlow如何玩转深度学习

自 2015 年 11 月 9 号发布之后&#xff0c;TensorFlow 逐渐成为人工智能领域最广泛运用的深度学习框架。TensorFlow 是一个大规模机器学习的开源框架&#xff0c;提供了多种深度神经网络的支持。不仅 Google 在自己的产品线使用 TensorFlow&#xff0c;包括联想、小米、新浪网…

巧用Newtonsoft.Json处理重复请求/并发请求?

背景一些用户请求在某些情况下是可能重复发送的&#xff0c;如果是查询类操作并无大碍&#xff0c;但其中有些涉及写入操作&#xff0c;一旦重复了&#xff0c;可能会导致很严重的后果。例如交易接口如果重复请求&#xff0c;可能会重复下单。问题假设我们把请求参数&#xff0…

java鼠标改变窗口大小监听事件_java – 当用户拖动鼠标时,监听JFrame调整事件大小?...

当用户单击JFrame的角落来调整大小并拖动鼠标时&#xff0c;JFrame会根据用户拖动时鼠标的当前位置重绘。你怎么听这些事件&#xff1f;下面是我目前尝试的&#xff1a;public final class TestFrame extends JFrame {public TestFrame() {this.addComponentListener(new Compo…

phpmyadmin 安装 配置

自己的试验成功后&#xff0c;写下&#xff01; 1.先到网上下载phpmyadmin&#xff0c;再解压到可以访问的web目录下&#xff08;如果是虚拟空间&#xff0c;可以解压后通过ftp等上传到web目录下&#xff09;&#xff0c;当然您可以修改解压后该文件的名称。 2.配置config文件 …

春节特惠活动┃数学无用论??我们欠孩子真正的数学阅读

▲数据汪特别推荐点击上图进入玩酷屋说到数学&#xff0c;我想起了13年一场轰动行业各界的“数学无用论”&#xff01;那时微博上有个话题叫做#让数学滚出高考#&#xff0c;超过7成网友都表示支持&#xff0c;这可怕的比例就能说明在中国由于数学差导致命运被洗牌的真不在少数……

EF Core中高效批量删除、更新数据的Zack.EFCore.Batch发布三个新特性

Zack.EFCore.Batch是一个支持在Entity Framework Core中高效删除和更新数据的开源库。我们知道&#xff0c;EF Core中不支持高效的删除和更新数据&#xff0c;所有的更新和操作都是逐条数据处理。比如&#xff0c;如果使用如下的语句删除实现“删除所有价格大于10元的书“&…

2012年,总结

2012年&#xff0c;神奇又平凡的一年。玛雅人的世界末日被普通的一天击破&#xff0c;自此买蜡烛的人就可以每天点着蜡烛做饭和炒菜了&#xff0c;用的还是当初囤积的食盐。 2012年&#xff0c;我就这样平淡的毕业了。就这样上班了&#xff0c;一切还没准备妥当&#xff0c;直到…

python pytest allure_python测试框架pytest和测试报告allure的联合使用-----测试套件

最近采用jenkinspythonpytestallure写了一些自动化测试用例。碰到这样一种场景&#xff1a;如果我创建了2个测试任务&#xff0c;测试任务1包含2个测试用例test_a.py和test_b.py&#xff0c;测试任务2包含一个测试用例test_c.py。一. 常规操作假设我的代码目录结构有如下3个测试…

那天,我无意间瞟了眼程序员的桌面……

全世界只有3.14 % 的人关注了数据与算法之美爱因斯坦曾说过“要是乱糟糟的桌面意味着杂乱无章的脑袋&#xff0c;那空白桌面意味着什么呢&#xff1f;似乎很多在某些领域拥有天赋的人都不喜欢干净整洁的桌面&#xff0c;包括乔布斯和扎克伯格也是&#xff0c;甚至有的人一看到整…

.Net Core with 微服务 - Ocelot 网关

上一次我们通过一张架构图&#xff08;.Net Core with 微服务 - 架构图&#xff09;来讲述了微服务的结构&#xff0c;分层等内容。从现在开始我们开始慢慢搭建一个最简单的微服务架构。这次我们先用几个简单的 web api 项目以及 ocelot 网关项目来演示下网关是如何配置&#x…

GNU ARM 汇编指令[转载]

http://blog.sina.com.cn/s/blog_59b189220100au1k.html 第一部分 Linux下ARM汇编语法尽管在Linux下使用C或C编写程序很方便&#xff0c;但汇编源程序用于系统最基本的初始化&#xff0c;如初始化堆栈指针、设置页表、操作 ARM的协处理器等。初始化完成后就可以跳转到C代码执行…