在java中有哪些锁

Python021

在java中有哪些锁,第1张

给你整理了Java中的一些锁:

公平锁/非公平锁

可重入锁

独享锁/共享锁

互斥锁/读写锁

乐观锁/悲观锁

分段锁

偏向锁/轻量级锁/重量级锁

自旋锁

上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计

先说一下synchronized的历史吧,在jdk1.6之前synchronized就是单纯一个重量级锁,在jdk1.6的时候,有一个叫Doug Lea的大哥看不过去了,明明很多情况都是不需要重量级锁的,只需要标记一下,所以这个大哥就开发一个ReentrantLock,无竞争的情况在java层面就完成了加锁解锁,这时候吧,jdk可能觉得面子上有点那啥,便开始优化synchronized,然后就产生了我们熟知的偏向锁,轻量级锁,重量级锁。

因为网上大部分的文章写mark word的解释基本都是基于32位jdk,这里我简单介绍一下64位jdk中,mark down的组成,和锁升级过程标志位的变化。

java的对象布局是由对象头、实例数据、数据对齐组成

但实际情况并不一定,后面我们引用下面的maven依赖来进行证明

发现没有数据填充的部分,这时候我们并不需要数据填充

(3)同理,我们将变量a删除后,没有了示例数据这一部分

对齐填充并不是必然存在的,也没有什么特别的意义,他仅仅起着占位符的作用,由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的大小必须是8字节的整数倍。而对象头正好是8字节的倍数,因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

对象头由两部分组成,一部分用于存储自身的运行时数据,称之为mark word,另外一部分是类型指针,及对象指向它的类元数据的指针。这里我们只研究一下mark word

OpenJdk官网对于mard word的定义

每个对象头的第一个字。通常是一组位字段,包括同步状态和标识哈希码。也可以是指向同步相关信息的指针(具有特征性的低位编码)。在GC期间,可以包含GC状态位。

我们再看hotspot的源码,里面有一段 注释

首先无锁、偏向锁、轻量锁大家应该都很清楚,但是图中的无锁可偏向和无锁不可偏向我在这里解释下,

我们知道偏向锁会在mark word中记录偏向线程的id,但是根据上图,我们可以发现,hashcode和偏向线程的id的位置是有冲突的,所以在不可偏向时就是我们计算了这个类的hashcode,这时候锁会直接升级成轻量级锁,后面我们会通过例子来证明。

这里我要先说明下,后面我们输出的mark word和我们期望的 在位置上是相反的,这是由于cpu的缘故,这里不做解释

jdk8中,有一个偏向锁的延迟开启,我们需要把延迟时间设置为0

-XX:BiasedLockingStartupDelay=0

首先我们可以看到 实例的hashcode和mark word里面标记的一样,并且现在是无锁不可偏向状态

下面不计算hashcode再看一下锁的标志位

Total time for which application threads were stop 超级长时间,这行日志代表什么,以及为什么时间会这么长

当GC发生时,每个线程只有进入了SafePoint才算是真正挂起,也就是真正的停顿,这个日志的含义是整个GC过程中STW的时间,配置了 -XX:+PrintGCApplicationStoppedTime 这个参数才会打印这个信息。

重点: 第一个 2.81 seconds 是JVM启动后的秒数,第二个 2.6 seconds 是 JVM发起STW的开始到结束的时间。特别地,如果是GC引发的STW,这条内容会紧挨着出现在GC log的下面。

有关安全点的详细说明,请移步:

JVM源码分析之安全点safepoint

[Java JVM] Hotspot GC研究- GC安全点 (Safepoint&Stop The World)

等待所有用户线程进入安全点后并阻塞,做一些全局性操作的行为。

配置 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 参数,虚拟机会打印如下日志文件:

RevokeBias、BulkRevokeBias、偏向锁取消情况。

Deoptimize、

G1IncCollectionPause GC GC 执行情况。

分析 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 产生的日志信息基本上STW的原因都是RevokeBias或者BulkRevokeBias。这个是撤销偏向锁操作,虽然每次暂停的 时间很短,但是特别频繁出现也会很耗时。

一些高并发的系统中,禁掉JVM偏向锁优化,可以提升系统的吞吐量 。禁用偏向锁的参数为: -XX:-UseBiasedLocking

R大分析类似情况

调优建议

各种JVM参数说明

stw分析

R大的博客

安全点 stw说明

偏向锁