高性能编程专题--多线程并发编程--锁的概念和synchronized关键字原理

在开始前,先介绍一下Java中有关锁的概念。
从不同的维度,锁可以有不同的分类方式:
乐观锁:假定没有并发冲突,在尝试修改数据时会有一个比较的过程,如果发现数据和之前获取的不一致,则读取最新数据,再次操作并重新尝试修改
悲观锁:假定一定会有并发冲突,直接同步所有对数据的相关操作,从读取数据就开始上锁

自旋锁:为了不放弃CPU执行时间,循环使用CAS技术对数据尝试进行更新,直至成功。自旋锁是一种乐观锁

独享锁(写):给资源加上写锁,该线程可以修改资源,其他线程不能再加锁(单写)
共享锁(读):给资源加上读锁后只能读不能修改,其他线程也能加读锁,并且读取数据,但是不能加写锁(多读)

可重入锁:线程拿到锁后,可以自由进入同一把锁同步的其他代码块
不可重入锁:线程拿到锁后,不能进入同一把锁同步的其他代码块

公平锁、非公平锁:按争抢锁的顺序分类,如果是按先来后到的,则为公平锁

synchronized

在Java中,同步关键字synchronized属于最基本的线程通信机制,是基于对象监视器实现的。Java中的每个对象都与一个监视器相关联,线程可以锁定或解锁监视器,并且同一时刻只有一个线程可以锁定监视器,其他试图锁定该监视器的线程都会被阻塞,直到它们可以获取到该监视器上的锁为止。
对于synchronized关键字,通常大家得第一反应是,这是一个重量级锁,开销很大,尽量避免使用。但是java6之后,对其进行了很多优化,性能有了大幅提高,建议大家多使用。

JIT优化

java6之后,JIT编译器在运行时会对synchronized锁进行优化
1.锁粗化:扩大锁的范围
如果我们编写了如下代码:

public void test (int i) {
	synchronized(this){
		i++;
	}
	synchronized(this){
		i++;
	}
}

经过JIT优化之后,代码实际运行可能会是这样的

public void test (int i) {
	synchronized(this){
		i++;
	//}
	//synchronized(this){
		i++;
	}
}

2.锁消除:对于不必要的加锁,在实际运行时会取消加锁解锁步骤

synchronized加锁原理与加锁优化

java6之后,提出了偏向锁,轻量级锁等概念,以提升无竞争和少量竞争下的优化。
默认情况下JVM锁会经历:偏向锁–>轻量级锁–>重量级锁的状态转变,同时,锁只会升级不会降级
参考来源:https://www.cs.princeton.edu/picasso/mats/HotspotOverview.pdf
https://wiki.openjdk.java.net/display/Hotspot/Synchronization

在这里插入图片描述
对象前面会有一个mark word,用于存储标识哈希值以及用于分代垃圾收集的年龄和标记位等。其中tag为状态位,01表示无锁,00表示轻量级锁,10表示重量级锁,11表示等待GC。如图,标识位的数据结构会随着锁的状态发生改变。
在这里插入图片描述
当一个对象被创建时,默认处于开启偏向锁和无锁状态,也就是偏向锁标识位1和锁状态位01,因此所有对象一开始都是可偏向的。
当线程需要获取锁时,
1.如果threadID为当前线程,则已获取到锁,不需要CAS获取锁,只会往当前线程的栈中添加一条Lock Record(用于统计重入次数),当退出同步块时,只会删除对应的Lock Record,不会修改threadID;
如果threadID为0,则会进行CAS将线程ID写入threadID位置,成功表示获取到锁;
如果获取锁失败,表示出现竞争,会准备撤销偏向锁;
如果threadID不为当前线程,表示出现竞争,会准备撤销偏向锁;
2.准备撤销偏向锁时,会检查持有偏向锁的线程状态,如果线程存活,并且还在同步块中,则升级为轻量级锁;
如果线程未存活,或者不在同步块中,则检查是否允许重偏向;
如果允许,则设置threadID为0,重新进入获取偏向锁逻辑;
如果不允许,则撤销偏向锁,升级为轻量级锁,将偏向锁标识位设为0,并判断是否有线程持有锁;
如果有,该线程获取到轻量级锁;
如果没有,则CAS争抢轻量级锁;
3.线程获取轻量级锁后,会将锁状态为设为0,当重入锁时,还是在当前线程的栈中添加一条Lock Record(用于统计重入次数);
4.升级为轻量级锁后,后面的线程想要获取锁时只会争抢轻量级锁,当CAS争抢一定次数(可设置次数)还未获取到锁时,升级为重量级锁,也就是对象监视器;
5.升级为重量级锁后,争抢锁的线程都会进入锁持等待,进入阻塞状态,不会再以CAS的方式争抢锁。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值