scala和java像不像_关于Java和Scala同步的五件事你不知道

scala和java像不像

实际上,所有服务器应用程序都需要在多个线程之间进行某种同步。 大多数同步工作是在框架级别为我们完成的,例如通过我们的Web服务器,数据库客户端或消息传递框架。 Java和Scala提供了许多组件来编写可靠的多线程应用程序。 这些包括对象池,并发集合,高级锁,执行上下文等。 blog_trampoline

为了更好地理解它们,让我们探索最同步的习惯用法-Object lock 。 这种机制为synced关键字提供了动力,使其成为Java中最流行的多线程习惯用法之一(如果不是)。 它也是我们使用的许多更复杂的模式的基础,例如线程和连接池,并发集合等等。

synced关键字在两个主要上下文中使用:

  1. 作为方法修饰符,用于标记一种方法,该方法一次只能由一个线程执行。
  2. 通过将代码块声明为关键部分 –在任何给定时间点仅一个线程可以使用一个代码块。

锁定说明

事实1 。 同步代码块使用两条专用字节码指令实现,这是官方规范的一部分-MonitorEnterMonitorExit 。 这与其他锁定机制(例如在java.util.concurrent包中找到的锁定机制)不同,该锁定机制是结合Java代码和通过sun.misc.Unsafe进行的本机调用来实现的(对于HotSpot而言)。

这些指令对开发人员在同步块的上下文中明确指定的对象进行操作。 对于同步方法,锁定将自动选择为“ this ”变量。 对于静态方法,锁将放置在Class对象上。

同步方法有时会导致不良行为 。 一个示例是在相同对象的不同同步方法之间创建隐式依赖关系,因为它们共享相同的锁。 更糟糕的情况是在基类(甚至可能是第3方类)中声明同步方法,然后将新的同步方法添加到派生类。 这会在整个层次结构中创建隐式同步依赖关系,并有可能导致吞吐量问题甚至死锁。 为避免这些情况,建议使用私有对象作为锁,以防止意外共享或逃脱锁。

编译器和同步

有两个字节码指令负责同步。 这是不寻常的,因为大多数字节码指令彼此独立,通常通过将值放在线程的操作数堆栈上来彼此“通信”。 还可以从操作数堆栈中加载要锁定的对象,该操作数堆栈先前是通过取消引用变量,字段或调用返回对象的方法来放置的。

事实#2。 那么,如果调用这两个指令之一而没有分别调用另一个指令会发生什么呢? 如果不调用MonitorEnter,Java编译器将不会生成调用MonitorExit的代码。 即使这样,从JVM的角度来看,这样的代码也是完全有效的。 这种情况的结果是MonitorExit指令抛出IllegalMonitorStateException。

如果通过MonitorEnter获得锁但没有通过对MonitorExit的相应调用释放锁,将会发生更危险的情况 。 在这种情况下,拥有该锁的线程可能导致其他试图获取该锁的线程无限期地阻塞。 值得注意的是,由于该锁是可重入的,因此拥有该锁的线程可能会继续愉快地执行,即使它再次到达并重新输入相同的锁也是如此。

这就是陷阱。 为了防止这种情况的发生,Java编译器以这样的方式生成匹配的输入和退出指令:一旦执行已进入同步块或方法,它就必须通过匹配的MonitorExit指令来处理同一对象。 可能会引起麻烦的一件事是,如果在关键部分内引发了异常。

public void hello() {synchronized (this) {System.out.println("Hi!, I'm alone here");}
}

让我们分析一下字节码–

aload_0 //load this into the operand stack
dup //load it again
astore_1 //backup this into an implicit variable stored at register 1
monitorenter //pop the value of this from the stack to enter the monitor//the actual critical section
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Hi!, I'm alone here"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)Vaload_1 //load the backup of this
monitorexit //pop up the var and exit the monitor
goto 14 // completed - jump to the end// the added catch clause - we got here if an exception was thrown -
aload_1 // load the backup var.
monitorexit //exit the monitor
athrow // rethrow the exception object, loaded into the operand stack
return

编译器用来防止栈不展开而无需通过MonitorExit指令的机制非常简单–编译器添加了一个隐式的try…catch子句以释放锁并重新抛出异常。

事实三 。 另一个问题是在相应的enter和exit调用之间存储的对锁定对象的引用在哪里。 请记住,多个线程可能会使用不同的锁对象同时执行同一同步块。 如果锁定的对象是调用方法的结果,则JVM极不可能再次执行它,因为它可能会更改对象的状态,甚至可能不会返回相同的对象。 对于自输入监视器以来可能已更改的变量或字段,情况也是如此。

监视变量 。 为了解决这个问题,编译器将一个隐式局部变量添加到方法中,以保存锁定对象的值。 这是一个明智的解决方案,因为与使用并发堆结构将锁定对象映射到线程(该结构本身可能需要同步)相比,该方法在维护对锁定对象的引用上的开销很小。 在构建Takipi的堆栈分析算法时,我首先观察到了这个新变量,并发现代码中弹出了意外变量。

注意,所有这些工作都是在Java编译器级别完成的。 JVM非常乐意通过MonitorEnter指令进入关键部分而不退出(反之亦然),或将不同的对象用作对应的enter和exit方法。

锁定在JVM级别

现在让我们更深入地研究如何在JVM级别上实际实现锁。 为此,我们将检查HotSpot SE 7的实现,因为这是VM特定的。 由于锁定可能会对代码吞吐量产生非常不利的影响,因此JVM进行了一些非常强大的优化,以尽可能高效地获取和释放锁定。

事实#4。 JVM所采用的最强大的机制之一是线程锁偏置 。 锁定是每个Java对象都具有的固有功能,就像具有系统哈希码或对其定义类的引用一样。 无论对象的类型如何,都是如此(如果您愿意,甚至可以使用基本数组作为锁)。

这些类型的数据存储在每个对象的标头(也称为对象的标记)中。 保留在对象标题中的某些数据保留用于描述对象的锁定状态。 这包括描述对象的锁定状态(即锁定/解锁)的位标志,以及对当前拥有该锁的线程的引用-指向该对象的线程有偏。

为了节省对象标头中的空间,为了减小地址大小并节省每个对象标头中的位(64位和32位JVM为54位或23位),在VM堆的较低段中分配了Java线程对象。分别)。

对于64位–

blog_normal-object

锁定算法

当JVM尝试获取对象的锁时,它会经历从乐观到悲观的一系列步骤。

事实五。 如果线程成功将其自身确立为对象锁的所有者,则该线程将获取该锁。 这取决于线程是否能够在对象的标头中安装对自身的引用(指向内部JavaThread对象的指针)。

获取锁。 使用简单的比较和交换(CAS)操作即可完成此操作。 这非常有效,因为它通常可以转换为直接CPU指令(例如cmpxchg)。 CAS操作以及OS特定的线程驻留例程用作对象同步习惯用法的构建块。

如果该锁是免费的,或者先前已对该线程进行了锁定,则将获得该线程的对象锁,并且可以立即继续执行。 如果CAS失败,则JVM将执行一轮自旋锁定,在该循环中线程停放以有效地使其在重试CAS之间进入睡眠状态。 如果这些初始尝试失败(向锁发出更高级别的争用信号),线程将自身进入阻塞状态,并使其自身进入争用该锁的线程列表,并开始一系列自旋锁。

在每轮旋转之后,线程将检查JVM全局状态的变化,例如“停止世界” GC的出现,在这种情况下,线程将需要暂停自身直到GC完成以防止出现这种情况。在执行STW GC时获得锁并继续执行的位置。

释放锁。 通过MonitorExit指令退出关键部分时,所有者线程将尝试查看它是否可以唤醒任何正在等待释放锁的驻留线程。 此过程称为选择“继承人”。 这是为了增加活动性,并防止在释放锁(也称为绞合)的情况下保持线程停放的情况。

调试服务器多线程问题很困难,因为它们往往取决于非常特定的时间安排和操作系统启发。 这就是让我们首先从事Takipi工作的原因之一。

参考:我们的JCG合作伙伴 Tal Weiss在Takipi博客上对Java和Scala中的同步不了解的5件事 。

翻译自: https://www.javacodegeeks.com/2013/08/5-things-you-didnt-know-about-synchronization-in-java-and-scala.html

scala和java像不像

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

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

相关文章

江南大学物联网工程学院数据库课程实验二作业2实验报告

一、开发环境 DBMS: Microsoft SQL Server 2019 (64- bit) 可视化管理工具: Microsoft SQL Server Management Studio- 18.10 二、代码、注释及测试 第三题 --创建客户表并且添加数据 create table customers( cnum varchar(5) primary key, --将客户编号设置为主键&#x…

BPSK调制下(2,1,6)标准卷积码及打孔生成2/3、3/4、4/5、5/6删余码Viterbi译码误码率曲线图(MATLAB实现)

关注公号【逆向通信猿】更精彩!!! 目录 仿真结果卷积码原理图删余后性能比较常用的删余码仿真代码根据码率生成打孔参数(子函数)将标准(2, 1, 6)编码后的序列进行打孔,生成删余码(子函数)对接收到的序列进行反打孔,将原来打孔删除的比特进行补零(子函数)BPSK调制下(2,1,6…

使用JDK 11在Java字符串上的新方法

Java的String类似乎将在JDK 11中获得一些新方法,该方法将于2018年9月发布。 错误号 错误标题 新的String方法 描述 JDK-8200425 字符串::行 lines() “使用专用的分隔符从源字符串中懒惰地提供行的字符串实例方法。” JDK-8200378 String :: strip&#x…

江南大学物联网工程学院数据库课程实验三作业3vb.net实验报告

一、开发环境 语言环境:Microsoft.NET Framework 4.6 SDK IDE:Microsoft Visual Studio Community 2015 二、代码及配置 1、Form1 Public Class Form1Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.LoadEnd SubPrivate …

[2021.07.25更新]循环冗余校验(CRC)的MATLAB实现

欢迎同步关注公众号【逆向通信猿】 CRC校验(循环冗余校验) 在计算CRC校验的时候,发现一个网站如下 http://www.ip33.com/crc.html 于是,想自己动手实现该网站计算CRC校验的功能,网站提供的在线计算工具是以十六进制来表示输入参数和结果的,为了方便MATLAB实现,本文提供…

江南大学物联网工程学院数据库课程实验四作业4vb.net实验报告

一、开发环境 语言环境:Microsoft.NET Framework 4.6 SDK IDE:Microsoft Visual Studio Community 2015 二、代码 Imports System.Data.SqlClient Public Class Form1 连接本机数据库并获取test_one数据库中的sc表数据 Dim mybind As BindingManagerB…

fftw库在windows下的的编译和配置

目录运行环境FFTW库的下载FFTW库的生成VS2017添加fftw库步骤运行环境 Visual Studio 2017 企业版 FFTW库的下载 首先在官网上下载fftw-3.3.5-dll32或fftw-3.3.5-dll64压缩包,解压。本人已经编译生成好的库下载地址:https://download.csdn.net/downloa…

深度学习在机器视觉应用领域的最新研究综述(物联网技术应用大作业)

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,无广告,忍不住分享一下给大家。(点击跳转人工智能学习资料) 摘要:机器视觉是人工智能正在快速发展的一个分支。简单说来&#xff0c…

MATLAB库函数hilbert(希尔伯特变换)的C语言实现(FFT采用FFTW库)

目录希尔伯特变换原理公式MATLAB官方帮助文档中希尔伯特变换算法常量和结构体定义C语言实现(FFTW库的float版,double版类似)希尔伯特变换原理公式 MATLAB官方帮助文档中希尔伯特变换算法 hilbert uses a four-step algorithm: Calculate the FFT of the input sequ…

netbeans7.4_NetBeans 7.4 Beta提示警告无效的异常处理

netbeans7.4有许多例子说明Java异常处理可能比首次出现时要困难得多,Josh Bloch专门将一整章的《 Effective Java》 (两个版本)专门用于异常处理。 Java中的检查异常模型 仍然 “ 有争议” 。 我很高兴看到我最近下载的NetBeans 7.4 beta有一…

在厚度仅十几微米的电池隔膜找缺陷?人工智能说,能行(人工智能应用案例)

原文链接:https://www.paddlepaddle.org.cn/support/news?actiondetail&id2104 “我们的质检要做的是在厚度仅十几微米的电池隔膜上找出所有微小缺陷,如果没有检测出来,就很可能使新能源汽车的电池在使用过程中出现问题,甚至…

MATLAB库函数unwrap(相位解卷绕)的C语言实现

什么是相位解卷绕 Q = unwrap(P) Q = unwrap(P) corrects the radian phase angles in a vector P by adding multiples of 2π when absolute jumps between consecutive elements of P are greater than or equal to the default jump tolerance of π radians. If P is a …

准确率超90%、1秒发出报警,人工智能助国网山东实现无人巡检(人工智能应用案例)

原文链接:https://mp.weixin.qq.com/s/Jh2YLY-4um79ucdHIs5NTg 众所周知,深度学习框架是人工智能的基础技术“底座”,在各大传统产业上也有着巨大的潜力尚待挖掘。5月20日,由深度学习技术及应用国家工程实验室与百度联合主办的“…

混合多云每个人都应避免的3个陷阱(第2部分)

如果您已经完全控制了内部数据中心,但又不能停止利用和支付过多的资源,那么如何期望防止这些成本转嫁到您的云策略中呢? 每天都在肆意宣传云,但每个人都应避免三个陷阱。 从云,混合云到混合多云,您被告知这…

MATLAB库函数upfirdn(分数倍采样率变换)的C语言实现【姊妹篇1基于std::vector】

upfirdn原理 yout = upfirdn(xin,h,p,q) upfirdn的功能在MATLAB官方帮助文档中说得很清楚 通过插零实现 p p p倍上采样对上采样之后的信号用给定的 h h h(通常为低通滤波器)进行滤波对滤波结果进行

基于PaddlePaddle实现高尔夫球场的遥感检测(人工智能应用案例)

原文链接:https://www.paddlepaddle.org.cn/support/news?actiondetail&id2103 1 . 背景及意义 随着高尔夫球运动在我国的兴起,关于高尔夫球场大量占用土地资源、污染环境、耗水量大且公益性差的争议越来越多。国家从2004年开始制定一系列相关政策…

在Jersey测试中模拟SecurityContext

泽西极有可能编写与泽西一起编写的REST-API集成测试。 只需扩展类JerseyTest并继续就可以了。 我遇到一个问题,我不得不模拟SecurityContext ,以便SecurityContext包含一个特殊的UserPrincipal 。 挑战在于Jersey在测试中将SecurityContext包装在自己的…

第一类修正贝塞尔函数的C语言实现

第一类修正贝塞尔函数公式 Iν(z)(z2)ν∑(k0)∞(z24)kk!Γ(νk1)I_{\nu}(z)\left(\frac{z}{2}\right)^{\nu} \sum_{(k0)}^{\infty} \frac{\left(\frac{z^{2}}{4}\right)^{k}}{k ! \Gamma(\nuk1)}Iν​(z)(2z​)ν(k0)∑∞​k!Γ(νk1)(4z2​)k​ 其中,Γ(a)\Gamma…

MATLAB库函数firls(最小二乘线性相位FIR滤波器设计)的C语言实现

firls函数功能 FILS设计了一种线性相位FIR滤波器,它可以最小化理想分段线性函数与滤波器在一组期望频带上的幅值响应之间的加权积分平方误差。 b = firls(n,f,a) b = firls(n,f,a,w) b = firls(n,f,a,ftype) b = firls(n,f,a,w,ftype)f是在0和1之间的范围内指定的频率点对的…

数电实验一-初识Multisim和Basys3

特别说明:该系列内容均是本人实验记录,无盗取侵权之嫌,仅供参考,请多动手实践! 一、实验目的 详见报告 二、实验仪器设备 详见报告 三、实验设计过程 使用Multisim为Basys3板卡创建一个PLD设计并进行验证。 1.创建P…