• 常见的锁策略


    目录

    一、乐观锁和悲观锁

    二、读写锁和普通互斥锁

    三、轻量级锁和重量级锁

    四、自旋锁和挂起等待锁

    五、公平锁和非公共平锁

    六、可重入锁和不可重入锁


    一、乐观锁和悲观锁

    乐观锁:预测锁冲突的概率较低,多个线程在访问锁对象时不会真的加锁,代码中需要做的工作量比较少。

    悲观锁:预测锁冲突的概率较高,多个线程在访问锁对象时都会进行真加锁,代码中需要做更多的工作。

    举个栗子:

            假设有两对情侣:男一号和女一号,男二号和女二号。

            乐观锁:男一号认为自己和女一号感情非常好,女一号不会和其他男生搞暧昧,所以偶尔才会问一下女一号:“你爱我吗?”

            悲观锁:男二号总是害怕女二号会绿他,即使在他们感情非常好的时候,他都要每天问女二号:“你爱我吗?”

    二、读写锁和普通互斥锁

    普通互斥锁:多个线程竞争同一把锁时,当一个线程竞争到锁之后,其他线程就阻塞等待。比如synchronized

    读写锁分为两种情况:

    加读锁:多个线程同时读一份数据时,不会有线程不安全的问题,所以没必要加锁。

    加写锁:多个线程同时写一份数据,或者有的线程写有的线程读同一份数据时,会有竞争,也就会有线程不安全问题,此时需要加锁。

    实际开发中,的场景一般会多于的场景,所以使用读写锁就会减少很多锁竞争的情况,优化程序的效率。

    三、轻量级锁和重量级锁

    轻量级锁:加锁、解锁的开销比较小。

            纯用户态的加锁逻辑,不涉及到进入内核的操作,因此开销比较小。

    重量级锁:加锁、解锁的开销比较大。

            需要进入内核态的加锁逻辑,开销就比较大。

    注意:

    轻量级锁和重量级锁是站在加锁解锁的结果来进行区分:

    重量级锁:加锁、解锁操作消耗的时间多。

    轻量级锁:加锁、解锁操作消耗的时间少。

    乐观锁和悲观锁是站在加锁的过程来进行区分:

    乐观锁:加锁的过程中需要做的工作比较少。

    悲观锁:加锁的过程中需要做的工作比较多。

    因此,乐观锁一般也是轻量级锁,悲观锁一般也是重量级锁,但这个结论并不绝对~

    四、自旋锁和挂起等待锁

    自旋锁:线程A和线程B竞争同一把锁,线程A竞争到之后,线程B会立刻尝试重新获取锁,无限循环,直到获取到锁为止。所以只要锁被线程A释放,线程B就会第一时间获取到锁,但是这样会消耗大量的CPU资源。自旋锁是纯用户态实现的。

    挂起等待锁:线程A和线程B竞争同一把锁,线程A竞争到之后,线程B进行阻塞等待,此时CPU就会空出来可以做其他的工作,但线程B获取到锁的时机可能并不会很及时。

    举个栗子:

            假设男生A约女生B一起吃饭,男生A早早来到餐厅等待~

            自旋锁:男生A会不停地打电话问女生B:“你到了吗?”当女生B到餐厅时,男生A就会立刻知道。

            挂起等待锁:男生A到餐厅后打个电话问女生B:“你到了吗?”女生B说:“还没有~”

    于是男生A就拿出手机刷视频,打游戏……所以当女生B到达餐厅时,男生A并不一定能及时知道。

    自旋锁适用于锁持有时间比较短的场景,更高效。如果锁的持有时间比较长,就会浪费CPU资源。

    挂起等待锁则适用于锁持有时间比较长的场景,可以合理利用CPU资源。 

    五、公平锁和非公共平锁

    公平锁:多个线程竞争同一个锁对象时,会遵循先来后到的规则。

    非公平锁:多个线程竞争同一个锁对象时,不遵循先来后到,而是谁抢到就是谁的。

    操作系统默认的锁的调度是非公平锁,要想实现公平锁,需要引入额外的数据结构来记录每个线程加锁的顺序,所以也需要花费额外的开销。

    举个栗子:

            假设有一群人都在等同一辆公交车~

            公平锁:所有人都自觉地排队上车,先来的排在前面,后来的排在后面。

            非公平锁:一群人都不讲武德,挤着上车。

    六、可重入锁和不可重入锁

    可重入锁:一个线程连续加锁两次,不会出现死锁的问题,比如synchronized

            synchronized会记录当前持有锁的线程,如果发现当前线程在释放锁之前再次进行加锁,就会让计数器自增,线程解锁,则计数器自减,当计数器为0时进行解锁操作,线程才会真正释放锁。

    不可重入锁:一个线程连续加锁两次,会出现死锁的问题。

  • 相关阅读:
    iOS hitTest 机制用处之二-----使用pointInside方法
    GEE开发之Modis_NDVI的数据分析
    金仓数据库KingbaseES 插件kdb_exists_expand
    不止于Kubernetes,开发人员应着眼于更多适合云原生应用的范式
    236. 二叉树的最近公共祖先 (Swift版本)
    亚马逊云科技云存储服务指南
    高精度乘法模板(fft)
    Mysql主从复制之slave_exec_mode,slave_skip_errors参数详解和测试
    华北理工大学计算机考研资料汇总
    MCS:离散随机变量——几何分布
  • 原文地址:https://blog.csdn.net/m0_67683346/article/details/127095233