有资源共享的地方就有竞争条件,有竞争条件就有线程安全,有线程安全就有线程同步,有线程同步就有锁。🔒 🔒
谈谈类型
有时候让我们对一个东西去做总结的时候其实挺乱的,因为不知道从什么维度去进行总结,又因为不知道从哪里去总结,所以随意总结了一下,导致重点归纳不到位。也许在不同的维度上,自己都有一个比较好的认知,但是却不能表述出来。这种能力是我比较稀缺的。
这种随意的总结偶尔会造成一个恶劣的后果,就是在给他们展示成果的时候,因为总结不到位,导致观众或者是评委看不到作品的全貌。一份随意的也不能够从多方面在展示的成果,只能是记流水账一样。因此,在总结的时候一定要从各个维度出发,针对这些维度它的表现形式是怎样的,是如何工作的,又达到了什么样的效果。
锁的类型
认知
如果对锁的应用维度不够了解,我们好像不能说出锁的啥类型,锁,不就是用来避免竞争条件,同步执行的么,还有啥类型么。
类型
- 锁住同步资源
- 🔒锁住—-> 悲观锁
- 不锁住 —-> 乐观锁
- 锁住同步资源失败,要不要阻塞
- 阻塞
- 不阻塞
- 自旋锁
- 适应性自旋锁
- 多线程竞争锁是否需要排队
- 需要—-> 公平锁
- 不需要-> 非公平锁 (先尝试,失败在排队)
- 一个线程是否可以多次获取同一把锁
- 能 —-> 可重入锁
- 不能—> 不可重入锁
- 多线程能否共享锁
- 能 —-> 共享锁
-
乐观和悲观
这两锁就是心态上的区别(读写量的区别)
悲观锁: 需要显示的调用
lock.lock
和lock.unlock
,Synchronizer
除外- Lock的实现
- Synchronizer
乐观锁
悲观锁适用于写多读少的情况
- 乐观锁适用于读多写少的情况
自旋
了解自旋锁首先需要了解,自旋锁解决了什么问题。线程的阻塞和唤醒需要CPU的参与,然后这两动作动静都比较大,上下文切换消耗比较大,在一些锁的时间很短的情况下,阻塞和唤醒
本身的操作比业务执行的更消耗资源。
自旋锁就是在这种背景下提出的。
自旋锁主要解决锁时间很短的时候避免阻塞和唤醒,而自旋锁如果一直自旋又会带来CPU计算浪费的问题,因此不能无限制自旋。只能尝试多少次,或者是多少时间内自旋来解决问题。
自旋是利用CAS来实现的
自适应自旋则是利用JVM本身的判断,上次自旋用了多久就获得锁了,这次是否依旧自旋。如果自旋很少获得锁,那就干脆不自旋了。
公平锁和非公平锁
公平锁是指大家一起排队,先进先出,第一个到达的第一个获得锁
- 好处: 都可以获得锁,不会出现线程饥饿的情况
- 缺点: 粒度不够,并发较低
非公平锁是线程先去获取一次,如果获取不到进入队列(这个时候就是公平锁了)
排他: 当前线程获取到资源后,其他线程只能等待