Java 锁

前言

各种花花绿绿的锁的充斥我们的眼球,在面对这么些个名词时:自旋锁,阻塞锁,可重入锁,读写锁,互斥锁,悲观锁,乐观锁,公平锁,偏向锁,对象锁,线程锁,锁粗化,锁消除,轻量级锁,重量级锁,独享锁,共享锁,分段锁的时候,我只想说…
在这里插入图片描述
但是,摸了摸干瘪的钱包,还是继续选择苟延残喘。

分类

在这里插入图片描述

锁的状态

在Java中,锁的状态可分为:

  1. 偏向锁:偏向于第一个获得锁的线程(可能只要一次cas 就完成了),假如没有其它线程来竞争,持有偏向锁的线程将永远不需要进行同步操作。
  2. 轻量级锁:当多个线程出现竞争了,偏向锁就不好使了,需要进行锁撤销并升级为轻量级锁,关于轻量级锁状态的保持,又有两种锁的设计方案,分别为自旋锁自适应自旋锁
  3. 重量级锁:自旋不可能无限循环下去(占用CPU资源),当一直没有获取到锁,线程就只能阻塞了

它们可以对应到锁的设计方案中,锁粗化(锁升级)过程中的各个状态。以Synchronized为例子。在JDK(1.5还是1.6…忘了)通过引入锁粗化的机制来优化Synchronized。这三种锁的状态是通过对象监视器在对象头中的字段来表明的,具体原理可以参考这位博主的文章

锁的设计方案

自旋锁/自适应的自旋锁

  1. 自旋锁:当一个线程申请一个已被占用的线程时,不一定就要立刻变为阻塞,有可能使用锁的线程很快会释放呢?此时,该线程可以不立刻让出CPU的控制权,先通过循环申请锁(自旋)的方式获取锁。如果成功,将省去线程阻塞时,用户态和内核态切换的功夫。
  2. 自适应的自旋锁: 自旋的时间不再固定的,而是由上一次在同一个锁上的自旋时间以及锁拥有者的状态来决定。如果在同一个锁对象上,某个线程刚刚通过自旋并成功获得过锁,那么,当它再次想自旋申请锁时,虚拟机就会认为这次自旋也是很有可能成功,进而它将允许自旋相对更长的时间。反之,如果自旋很少成功获得过,那在以后尝试获取这个锁时将可能省略掉自旋过程,直接阻塞线程,避免浪费处理器资源。

看过AQS(或其他JDK源码)的实现的朋友,可以发现JDK很多地方采用for(;;)+cas的方式来申请锁,其实这就就是自旋 的一种具体实现。

锁粗化/锁消除

  1. 锁粗化:细粒度下的锁控制需要耗费大量资源时,改为粗粒度的锁。一种是synchronized的锁状态升级过程。还有一种,多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁,即将加锁的粒度放大。

  2. 锁消除:虚拟机即时编译器在运行时,被要求同步的代码块被检测到不可能存在共享数据竞争时,锁就会被消除。(感谢逃逸分析

分段锁

  1. 分段锁:当多个线程操作一个集合的时候,不一定就要将一整个集合进行加锁。可以采用这种方式,将存储在集合里头的数据进行分段。只有某个段被多个线程同时操作时,才需要对这个段进行加锁,其它则不用,从而提高效率。

JDK 1.7中的ConcurrentHashMap可以说是分段锁方案的实现的重要代表了。不过JDK 1.8中采用了synchronized+cas方式进行实现,估计原来的设计太臃肿了,另外JDK 1.8 HashMap引入了红黑树的存储结构(ConcurrentHashMap存储数据的结构还是来源于HashMap),该结构在分段处理上可能也是有些麻烦。

锁的特性/性质

公平锁/非公平锁

  1. 公平锁:多个线程竞争同一把锁,按申请顺序获取锁。
  2. 非公平锁:反之。

Java中,Synchronized就是一种非公平锁的实现,ReentrantLock(重入锁)则提供了Nonfair和fair两种方式。如果时Nonfair,会再申请锁时就先进行一遍CAS。

共享锁/独享锁

  1. 共享锁:该锁可被多个线程所持有。(ReadLock)
  2. 独享锁:占有锁后其他线程不能持有。(WriteLock、Synchronized)

关于互斥锁/读写锁,个人则认为是共享锁/独享锁一种具体实现,如ReentrantLock就是一种互斥锁。ReentrantReadWriteLock则是一个读写锁。

乐观锁/悲观锁

乐观锁与悲观锁同样也不是具体的锁实现,而是看待并发同步的角度。

  1. 乐观锁:认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,则采用尝试更新+重试的方式更新数据。(CAS)
  2. 悲观锁:认为对于同一个数据的并发操作,一定会发生修改的,因此对于同一个数据的并发操作采取加锁的形式。

Java中的原子类就是以乐观锁的方式进行数据更新,其本质也是CAS算法的支持。另外,MySQL的MVCC也是乐观锁的一种实现方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

legendaryhaha

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值