Java EE 多线程之锁策略

1. 锁策略

锁策略是,在加锁的过程中,处理冲突的过程中,涉及到的一些不同的处理方式
此处的锁策略,并非是 java 独有的
这里的锁策略,一般是“设计锁”所需要的知识

2. 乐观锁 和 悲观锁

乐观锁:在加锁之前,预估当前出现锁冲突的概率不大,因此在进行加锁的时候就不会做太多的工作

加锁过程做的的事情比较少,加锁的速度可能就比较快,但是很容易引入一些其他的问题(但是可能会消耗更多的 cpu 资源)


悲观锁:在加锁之前,预估当前锁冲突出现的概率比较法,因此加锁的时候,就会做跟多的工作

做的事情更多,枷锁的速度可能更慢,但是整个过程中不容易出现其他问题

3. 轻量级锁 和 重量级锁

轻量级锁:加锁的开销小,加锁的速度更快
轻量级锁,一般就是乐观锁


重量级锁:加锁的开销更大,加锁速度更慢
重量级锁,一般就是悲观锁


轻量重量级锁,是加锁之后,对结果的评价
悲观乐观锁,是加锁之前,对未发生的事情进行的评估

整体来说,这两种角度,描述的是同一个事情

4. 自旋锁 和 挂起等待锁

自旋锁:是轻量级锁的一种典型实现

进行加锁的时候,搭配一个 while 循环,如果加锁成功,自然循环结束
如果加锁不成功,不是阻塞放弃 cpu,而是进行下一次循环,再次尝试获取到锁

这个反复快速执行的过程,就称为“自旋”
一旦其他线程释放了锁,就能第一时间拿到锁

同时,这样的自旋锁,也是乐观锁
使用自旋的前提,就是预期锁冲突黛绿不大,其他线程释放了锁,就能第一时间拿到
如果当前加锁的新城特别多,自旋意义就不打了,白白浪费 cpu


挂起等待锁:就是重量级锁的一种典型实现
同时也是一种悲观锁
挂起等待的时候,需要内核调度器介入,这个时候真正拿到锁需要花费的时间会很多

同时,这个锁也是一种悲观锁,这个锁可以适用于锁冲突激烈的情况

5. 普通互斥锁 和 读写锁

普通互斥锁:类似于 synchronized ,操作涉及到 加锁 和 解锁


读写锁:这里的读写锁,把加锁分为两种情况

  1. 加读锁
  2. 加写锁

读锁和读锁之间,不会出现锁冲突(不会堵塞)
写锁和写锁之间,会出现锁冲突(会堵塞)
读锁和写锁之间,会出现锁冲突(会堵塞)
也就是:读的时候,不能写,只能读;写的时候,不能读,也不能写


为什么要引入读写锁?

如果两个线程读,本身就属于线程安全,不需要互斥
如果使用 synchronized 这种凡是加锁,两个线程读,也会产生互斥,产生阻塞
如果完全给读操作不加锁,也不行,因为一个线程读一个线程写,很可能会读到写了一半的数据
这个时候引入读写锁,就可以解决上述问题
在实际开发中,读写锁很常见,因为读操作非常常见,读写锁可以把并发读之间的锁冲突的开销省下,对于性能提升显著

在标准库中,也提供了专门的类,实现读写锁(本质上还是系统提供的读写锁,提供的api)

6. 公平锁 和 非公平锁

这里的“公平”,是遵循先来后到的规则

公平锁:遵循先来后到的顺序,前面的释放锁,后面在拿到锁


非公平锁:站在系统原生的锁的角度,就是属于“非公平锁,系统线程的调度本身就是无序的随机的

synchronized 就是非公平锁

要想实现公平锁,就需要引入额外的数据结构(引入队列,记录每个线程先后顺序),才能实现公平锁

使用公平锁,天然就可以避免线程饿死的问题

6.可重入锁 和 不可重入锁

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


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

synchronized 是可重入锁
系统自带的锁,是不可重入锁

可重入锁种需要记录持有锁的线程是谁,加锁的次数的计数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

柒柒要开心

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

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

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

打赏作者

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

抵扣说明:

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

余额充值