各种锁的机制

根据锁的特性来进行分类

1、乐观锁和悲观锁

悲观锁: 对于一个数据的并发操作,悲观锁认为自己在使用数据的时候一定会有别的线程来修改数据,因此就要先加锁,确保数据不会被其他线程修改。synchronized关键字和Lock的实现类都是悲观锁。

乐观锁: 自己在使用数据的时候不会有其他线程来修改数据的,因此不会添加锁,只是在更新数据之前去判断这个数据是否被修改。如果已经被修改,那就根据不同的实现方式执行不同的操作(例如报错或者自动重试);如果没有被更新,那就将自己修改的数据成功写入。CAS算法就是使用无锁编程来实现的,是乐观锁。

在这里插入图片描述
根据上面的分析我们可以看出:

悲观锁适合写操作多的场景,先加锁可以保证写操作时数据正确
乐观锁适合读操作多的场景,不加锁能使其读操作的性能大幅度提升

悲观锁很容易理解,咱们现在来看一下乐观锁——CAS算法

CAS全称 Compare And Swap(比较与交换),是一种无锁算法。在不使用锁(没有线程被阻塞)的情况下实现多线程之间的变量同步。java.util.concurrent包中的原子类就是通过CAS来实现了乐观锁。

CAS算法涉及到三个操作数:

  1. 需要读写的内存值 V
  2. 进行比较的值 A
  3. 要写入的新值 B

当且仅当 V 的值等于 A 时,CAS通过原子方式用新值B来更新V的值(“比较+更新”整体是一个原子操作),否则不会执行任何操作。一般情况下,“更新”是一个不断重试的操作

乐观锁的三大问题:

  1. ABA问题。CAS需要在操作值的时候检查内存值是否发生变化,没有发生变化才会更新内存值。但是如果内存值原来是A,后来变成了B,然后又变成了A,那么CAS进行检查时会发现值没有发生变化,但是实际上是有变化的。JDK 1.5 以后的 AtomicStampedReference类就提供了此种能力,其中的 compareAndSet 方法就是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。
  2. 循环时间长开销大。CAS操作如果长时间不成功,会导致其一直自旋,给CPU带来非常大的开销。
  3. 只能保证一个共享变量的原子操作。对一个共享变量执行操作时,CAS能够保证原子操作,但是对多个共享变量操作时,CAS是无法保证操作的原子性的。

2、自旋锁 VS自适应自旋锁

自旋锁的概念:当一个线程尝试去获取某一把锁的时候,如果这个锁此时已经被别人获取(占用),那么此线程就无法获取到这把锁,该线程将会等待,间隔一段时间后会再次尝试获取。

自适应意味着自旋的时间(次数)不再固定,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。

3、无锁 VS 偏向锁 VS 轻量级锁 VS 重量级锁

无锁: 无锁没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功。

偏向锁: 一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价。偏向锁只有遇到其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁,线程不会主动释放偏向锁。

轻量级锁: 当锁是偏向锁的时候,被另外的线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。

重量级锁: 若当前只有一个等待线程,则该线程通过自旋进行等待。但是当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁升级为重量级锁。

在这里插入图片描述

4、公平锁 VS 非公平锁

公平锁:
是指多个线程按照申请锁的顺序来获取锁,类似排队打饭,先到先得。
非公平锁:
是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁在高并发的情况下,有可能会造成优先级反转或者饥饿现象

5、可重入锁 VS 非可重入锁

ReentrantLock和synchronized都是重入锁

可重入锁:
有多个人在排队打水,此时管理员允许锁和同一个人的多个水桶绑定。这个人用多个水桶打水时,第一个水桶和锁绑定并打完水之后,第二个水桶也可以直接和锁绑定并开始打水,所有的水桶都打完水之后打水人才会将锁还给管理员。这个人的所有打水流程都能够成功执行,后续等待的人也能够打到水。这就是可重入锁

非可重入锁
此时管理员只允许锁和同一个人的一个水桶绑定。第一个水桶和锁绑定打完水之后并不会释放锁,导致第二个水桶不能和锁绑定也无法打水。

6、独享锁 VS 共享锁

独享锁也叫排他锁,是指该锁一次只能被一个线程所持有

共享锁是指该锁可被多个线程所持有

参考自:https://blog.youkuaiyun.com/axiaoboge/article/details/84335452

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值