多线程之常见的锁策略

本文介绍了并发编程中的锁策略,包括乐观锁和悲观锁的概念及其区别,读写锁的应用,以及重量级锁、轻量级锁、自旋锁和挂起等待锁的实现与优缺点。此外,还讨论了可重入锁和公平锁与非公平锁的特性。
摘要由CSDN通过智能技术生成
最近复习了一遍锁策略,虽然锁策略在实际工作中需求不大,但经常出现在面试题中,以下帮助读者快速熟悉常见的锁策略

乐观锁与悲观锁

悲观锁(锁冲突概率高,工作复杂)

悲观锁认为多个线程访问同一个共享变量冲突概率大,会在每次访问前真正的加锁,悲观锁的实现就是先加锁, 获取到锁再操作数据. 获取不到锁就等待

乐观锁(锁冲突概率低,工作简单)

乐观锁认为多个线程访问同一个共享变量冲突的概率不大. 并不会真的加锁, 而是直接尝试访问数

据. 在访问的同时识别当前的数据是否出现访问冲突.乐观锁的实现可以引入一个版本号. 借助版本号识别出当前的数据访问是否冲突.

例如

A和B是合租的室友,A去上厕所比较乐观,决定B不会进来,就不给厕所锁门了,B比较悲观,觉得A一天天的很喜欢上厕所,担心A突然闯进厕所,所以必须锁门

读写锁与普通互斥锁

读写锁就是把读操作和写操作分别进行加锁

多线程之间,当多个线程同时读取数据不会产生线程安全问题,但是同时写入数据或者边写边读就会导致线程不安全,因此就需要使用普通互斥锁(synchronized),但是如果只涉及读取,使用互斥锁会造成极大的性能损耗,因此出现了读取锁

读写锁需要在执行时候表明此次加锁的目的,是读还是写呢,如果是读不需要互斥,如果是写需要互斥。

  • 读锁和读锁,不竞争

  • 读锁和写锁,有竞争

  • 写锁和写锁,有竞争

重量级锁与轻量级锁

重量级锁:加锁解锁的开销大,用户态的加锁逻辑

轻量级锁:加锁解锁的开销小,进入内核态的加锁逻辑

理解内核态和用户态:

例如去银行办理业务,我需要复印一份存折,此时自己去银行的复印件操作属于用户态,让柜台工作人员帮我去操作属于内核态,内核态时,工作人员可能和其他人说话或者给其他客人解决问题,所以导致时间不确定,因此导致效率低下。

自旋锁与挂起等待锁

举一个简单的例子,小A(自旋锁)和小B(挂起等待锁)同时追求一个女生,此时这个女生有男朋友,两个人采取不同的追求策略,小A就死等这个女生分手,当这个女生分手后,小A马上获得了和该女生交往的机会,小B在女生有对象的时候,没有在一颗树上吊死,去做了其他的事情,当这个女生分手后的很长时间,询问小B要不要交往(此时女生可能已经换了很多男朋友了)

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

  • 优点:没有放弃cpu,不涉及阻塞和调度,一旦锁被释放,第一时间获取到锁

  • 缺点:如果锁被其他线程占用时间过长,会持续消耗cpu资源

挂起等待锁是一种典型的重量级锁的实现方式

  • 优点:等待时间里,cpu可以做点别的事情,节省cpu的资源浪费

  • 缺点:获取锁的时间长

可重入锁与不可重入锁

可重入锁:

允许同一个线程多次获取同一把锁(synchronized是可重入锁)

不可重入锁:

允许同一个线程多次获取同一把锁

公平锁与非公平锁

如果有ABC三个线程,当A线程先尝试获取锁,获取成功后,B线程尝试获取锁,锁被占用,获取失败,阻塞等待,最后C线程也尝试获取锁,也获取失败,阻塞等待。

当A线程释放锁后,会出现什么情况呢?

公平锁:遵循“先来后到”,B比C先来的当A释放锁后,B就先于C获取锁

非公平锁:不遵循"先来后到",即使B比A先来,但是B和C都有可能获取到锁,取决于操作系统的调度

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值