常见锁策略

 

目录

1. 乐观锁 VS 悲观锁

2. 轻量级锁 VS 重量级锁

3. 自旋锁 VS 挂起等待锁

4. 读写锁

5. 可重入锁 VS 不可重入锁

6. 公平锁 VS 非公平锁

7. 关于 synchronized 的锁策略


为保证线程安全,我们常常进行加锁操作,那在 Java 中都有哪些 锁策略呢?

1. 乐观锁 VS 悲观锁

    乐观悲观与否,取决于后续锁冲突是否激烈(频繁)给出的预测。

  (1)乐观锁:预测 后续 锁冲突较小,就可以少做一些工作。

  (2)悲观锁: 预测 后续 锁冲突较大,就需要多做一些工作。

2. 轻量级锁 VS 重量级锁

    重量,轻量 是看 锁开销大小来决定的。

  (1)轻量级锁:锁开销相对较小。  通常也就是轻量级锁(不一定)

         典型的是纯用户态的加锁解锁逻辑,开销是比较少的。

  (2) 重量级锁: 锁开销相对较大。 通常也就是重量级锁(不一定)

         典型的是进入了系统内核态的加锁解锁逻辑,开销是比较大的。

3. 自旋锁 VS 挂起等待锁

  (1)自旋锁:属于轻量级锁的一种典型的实现。

       自旋锁会反复 获取 锁的状态,属于”忙等(一直等,啥事不干)“,直到获取到锁。

       虽然这消耗了 cpu 的资源,但是 换来了 更快的响应速度

  (2) 挂起等待锁: 属于重量级锁的一种典型实现。

       挂起等待锁 需要借助 系统api 来实现,当出现锁竞争的时候,线程就会阻塞,并且该线程就不会参与 cpu 的调度了,节省了cpu 资源。

4. 读写锁

    这里的读写锁 与 数据库中 ” 事务“ 中的 给读加锁 和 给写加锁 不一样。

    读写锁 , 是将 加锁操作,分为了 读锁 以及 写锁 。 

    当我们两个线程之间进行加锁过程中:

        1. 读锁 与 读锁 之间 : 不会产生 竞争 。

        2. 读锁 与 写锁 之间 :有竞争。

        3. 写锁 与 写锁 之间 :有竞争。

     由于我们 实际的开发的过程中,大多是 ” 读多,写少“的情况,此时读写锁就排上用场。

5. 可重入锁 VS 不可重入锁

    重入与否 ,取决于 当一个线程针对一把锁 进行多次加锁,是否会出现 ”死锁“ 的情况

  (1)可重入锁:针对上述情况,不会出现 “死锁” 问题。

       可重入锁为什么不会出现 ”死锁“ 的情况呢:

       这是因为可重入锁中引入了 计数器,首先它会先记录是谁获取的这把锁,如果是相同的线程再继续获取,它就会把计数器进行+1.

  (2) 不可重入锁: 连续加锁多次就会出现 ”死锁“ 问题。

       不可重入锁就没有 可重入锁的机制,所以就会出现死锁。

6. 公平锁 VS 非公平锁

    当很多线程 尝试去对一把锁进行加锁操作时,一个线程拿到锁,其他线程就只能阻塞等待,当这个线程释放锁之后,接下来是哪个线程获取锁呢?

    公平,非公平就是针对这个问题来定义的。

  (1) 公平锁: 按照 ”先来后到“ 的顺序进行 获取锁的操作。

 

  (2)非公平锁: 线程以 ”均等“ 的概率获取锁。(操作系统中提供的 加锁 api 就属于这种)

7. 关于 synchronized 的锁策略

  (1)既是乐观锁,也是悲观锁

  (2)既是轻量级锁,也是重量级锁

  (3)既是自旋锁,也是挂起等待锁

  (4)不是读写锁,是普通互斥锁

  (5)是非公平锁

  (6)是可重入锁

       synchronized 是自适应的:在初始情况下,synchronized 会先预测当前 锁冲突 的概率,如果概率不大,就会以乐观锁的模式来运行(轻量级锁,基于自旋锁的方式实现);后续,当锁冲突变大时,它就会升级为 重量级锁(悲观锁,基于挂起等待锁的方式实现)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值