用上厕所说明锁

什么是锁:

多线程访问同一个资源,就好像上厕所一样,谁先挤进去就得把门锁上。这个“锁”是所有人共享的,但是每个人的钥匙是不一样的。每个人都要自己加锁(实际上是内核设置锁的性质),拿锁则是问管理员(内核)要。所以我们关注的是不同种类的上厕所者,加的是什么锁。

互斥锁和自旋锁是很多高级锁的基类

互斥锁加锁成功后,会让其他拿锁的线程释放cpu进入睡眠。意味着线程会在睡着和醒来之间切换两次。
这就是开销,时间成本很小,但是加锁时间有可能比执行的代码还长。

自旋锁则会让拿锁的线程进入忙等待状态,意味着没有线程切换成本。而且自旋锁 和忙等待都是通过硬件级别的指令实现的,开销更小。
线程忙等待的时候 和 被锁住的代码执行时间是成正比的。

读写锁

由读锁和写锁两个部分组成,如果只读共享资源就加读锁,修改就加写锁。
所以读写锁适用于能够明确区别读写的场景。
那么这是怎么实现的?

  • 当写锁没有被人加上的时候,也就是没人要泄了,大家都可以去厕所里面看马桶。但是一旦有人要泄了,就不允许来看。更不允许进来。

所以说写锁是独占锁,因为任何时刻只有一个线程持有,类似互斥锁和自旋锁,而读锁是共享锁,因为读锁可以被多个线程持有。

在这里插入图片描述

写优先锁

顾名思义,优先写线程,泄的先上。上一批已经在厕所里的人我可以等一会,但是后来的不准插队。

在这里插入图片描述读优先锁对于读并发性更好,但也不是没有问题。
试想一下,如果一直有读线程获取读锁,那么写线程将会很饥饿。
写优先同理。
于是乎

公平读写锁

这种锁一看就很公平,比较简单的实现是:用队列把获取锁的线程排队。
其实就是原来的读写锁,读或者写都有一个能插队,现在我不让你插队。

乐观锁和悲观锁

前面提到的 互斥、自旋、读写,都实现了进厕所关门认为不关门的话会有很可怕的后果,所以都是悲观的。

那什么是乐观的呢:我先上,我也不关门,你要上就上。我等会再来。那么问题来了:
如果乐观锁憋不住了怎么办?岂不是要拉一裤裆。
所以如果乐观锁重写成本*重写概率 大的话,就会有可怕的后果。当然是自己承担了。

因此,乐观锁全程没有加锁,也叫无锁编程。

比如:在线文档

我们知道在线文档是支持多人同时编辑的,编辑完提交后再查看是否有冲突发生。
怎么算是打架了? 举个栗子:牛马在浏览器编辑文档,出生在同样的地方编辑还提交了,这个时候牛马提交的时候就会打架。你怎么占了我的坑?

服务端冲突验证:

  • 由于冲突概率低,先让用户编辑,但是浏览器在下载文档的时候会记录服务端返回的文档版本号。
  • 当用于提交修改时候,发给服务端的请求会带上原始文档版本号,服务器收到后将它与当前版本号进行比较,如果版本号一致则修改成功,否则提交失败。

实际上SVN和Git也使用了乐观锁思想,先让用户编辑代码,然后提交的时候,通过版本号来判断是否产生了冲突,发生了冲突的地方需要你自己判断后重新提交。

乐观锁虽然去除了加锁解锁的操作,但是一旦发生冲突,重试的成本非常高,所以只有在冲突概率非常低,且加锁成本非常高的场景时,才考虑使用乐观锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

~Yogi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值