多线程——这些锁策略你知道吗?

各种锁策略

  • 1、乐观锁VS悲观锁
  • 2、读写锁
  • 3、重量级锁vs轻量级锁.
  • 4、挂起等待锁VS自旋锁
  • 5、公平锁Vs非公平锁
  • 6、可重入锁
  • 7、死锁的典型场景
  • 8、针对sychronized

1、乐观锁VS悲观锁

乐观锁: 世界大概率是和平的,多个线程竞争一 把锁的概率会很低.(效率高)
悲观锁: 世界大概率是出问题的,多个线程竞争一 把锁的概率会很高,会付出更多的成本来进行锁冲突的处理(更安全)

两种想法没有优劣之分,要根据具体场景来进行使用.

2、读写锁

把加锁操作分成了两种.
a)读锁
b)写锁

读锁和读锁之间是没有互斥的(不存在锁竞争)
读锁和写锁/写锁和写锁之间才进行互斥.

如果某个场景下"-写多读"
使用读写锁效率就很高,写操作少,读操作多这样冲突就少。
多线程——这些锁策略你知道吗?_第1张图片

3、重量级锁vs轻量级锁.

加锁需要保证原子性.原子性功能来源自硬件. (硬件提供了相关的原子操作的指令,操作系统封装一下成为原子 操作的接口,应用程序才能使用这样的操作)
重量级锁
在加锁过程中,如果整个加锁逻辑都是依赖于操作系统内核 (代码在内核中的执行开销会比较大)
轻量级锁.
对应的,如果大部分操作都是用户自己完成,少数操作由内核完成

举例:
去银行办卡,自己填写单子,这就是用户应用程序的操作.
把单子交给银行柜员,柜员就要一顿操作. 具体操作多久,不可控的.相当于内核态执行代码.

4、挂起等待锁VS自旋锁

挂起等待锁
表示当获取锁失败之后,对应的线程就要在内核中挂起等待(放弃CPU,进入等待队列),需要在锁被释放之后由操作系统唤醒.(通常都是重量级锁)

自旋锁
表示在获取锁失败后,不会立刻放弃CPU,而是快速频繁的再次询问锁的持有状态- -旦锁被释放了,就能立刻获取到锁.(通常都是轻量级锁)

自旋锁的效率更高(线程能够获取CPU资源是一件来之不易的事情,一旦线程挂起,下次啥时候能被调度上,就不可预期了. (时间可能很久,能够达到ms级,极端情况下可能是s级)),但是会浪费一些 CPU资源(自旋过程相当于CPU在空转)

5、公平锁Vs非公平锁

如果多个线程都在等待一把锁的释放.
当锁释放之后,恰好又来了一个新的线程也要获取锁

公平锁: 能保证之前先来的线程优先获取锁.
非公平锁: 新来的线程直接获取到锁,之前的线程还得接着等

6、可重入锁

一个线程针对一把锁,连续加锁两次不会死锁,这种就是可重入锁.

如果锁记录自己是被谁持有的,就可以进行特殊判定了.
当锁的持有者正好就是新的锁的申请者,此时就特殊处理下让加锁操作成功即可.

7、死锁的典型场景

1.一个线程针对一把锁连续加两次
2.两个线程针对两把锁分别加锁
3. N个线程针对N把锁分别加锁.哲学家就餐问题

8、针对sychronized

1.开始是乐观锁, 一定条件下转为悲观锁
2.开始是轻量级锁, 一定条件下膨胀为重量级锁
3.实现锁的时候使用的是自旋锁
4.不公平锁
5.是一个可重入锁
6.不是读写锁

你可能感兴趣的:(多线程,内核,多线程,java,并发编程,操作系统)