阻塞锁和自旋锁的理解

简介: 总体来说,自旋锁适用于锁定时间短、锁竞争不频繁的场景,而阻塞锁更适合锁定时间较长或锁竞争较频繁的场景。根据具体的应用需求选择合适的锁类型,可以优化系统性能。

阻塞锁

阻塞锁就像是在排队时坐下来等。假设你们有一个椅子,只有轮到你时你才可以站起来玩。如果轮到你的朋友玩,你就坐在椅子上休息,等轮到你时再站起来。这种方式的好处是你可以省力,不用一直站着等。


自旋锁

自旋锁就像是在排队时站着不停地走动。假设你们站成一排等待,每个人都一直走来走去,随时准备轮到自己。这种方式的好处是当轮到你时,你可以马上开始玩,因为你已经准备好了。不过缺点是你会一直走来走去,可能会有点累。


在计算机里面,当不同的程序需要访问同一个资源(比如一段数据)时,它们需要排队,避免同时使用导致错误。阻塞锁和自旋锁就是用来解决这个问题的两种方法:


阻塞锁:程序会停下来等待,直到资源可用。这就像坐下来休息,等轮到自己。

自旋锁:程序会不停地检查资源是否可用,这就像一直走来走去,随时准备使用资源。

总结一下,阻塞锁更省力,但是等待时间可能会稍长;自旋锁更快,但是会占用更多的计算资源。不同的情况下,程序会选择不同的锁来使用。


阻塞锁

阻塞锁是指当线程尝试获取锁失败时,线程进入阻塞状态,直到接收信号后被唤醒.(线程的状态包括新建、就绪、运行、阻塞及死亡)在JAVA中,能够唤醒阻塞线程的操作包括Object.notify, Object.notifyAll, Condition.signal, LockSupport.unpark。


阻塞锁在获取锁失败后,会进行阻塞,这时涉及到cpu的上下文切换。再唤醒时,也需要重新去获取cpu时间片,也需要上下文切换。


自旋锁

线程在一个循环中尝试获取锁,直到获取到锁为止。此时该线程会一直占用cpu,直到获取到锁才释放。但是由于一直在尝试获取锁中,所以执行速度会比阻塞锁快。


各自的优缺点

自旋锁

优点:


低延迟:自旋锁的等待时间通常很短,因为它只是简单地检查锁是否可用,没有涉及操作系统的调度开销。

简单实现:自旋锁的实现通常比较简单,不需要涉及复杂的操作系统机制。

适用于短时间等待:在锁定时间非常短的情况下,自旋锁可以非常高效,因为它避免了线程上下文切换的开销。

缺点:


高CPU使用率:自旋锁会不断地检查锁的状态,占用大量的CPU资源,可能导致CPU浪费。

不适合长时间等待:如果锁被占用的时间较长,自旋锁会导致大量的资源浪费,因此不适合长时间等待的场景。

可能导致优先级反转:在某些情况下,自旋锁可能会导致低优先级线程占用CPU时间,从而延迟高优先级线程的执行。

阻塞锁

优点:


节省CPU资源:阻塞锁在等待时会将线程挂起,让出CPU资源,其他任务可以继续执行。

适用于长时间等待:如果锁被占用的时间较长,阻塞锁更合适,因为线程会被挂起,直到锁可用。

减少资源竞争:通过挂起线程,阻塞锁减少了资源竞争和系统开销。

缺点:


高延迟:由于涉及操作系统的调度和线程上下文切换,阻塞锁的等待时间可能较长。

复杂实现:阻塞锁的实现需要依赖操作系统的调度机制,通常比自旋锁更复杂。

可能导致上下文切换开销:如果线程频繁地被挂起和唤醒,可能导致大量的上下文切换开销。

选择自旋锁还是阻塞锁

短时间锁定:如果预计锁定时间非常短,自旋锁可能更高效,因为避免了线程挂起和唤醒的开销。

长时间锁定:如果预计锁定时间较长,阻塞锁更合适,因为可以节省CPU资源。

总阻塞锁

阻塞锁就像是在排队时坐下来等。假设你们有一个椅子,只有轮到你时你才可以站起来玩。如果轮到你的朋友玩,你就坐在椅子上休息,等轮到你时再站起来。这种方式的好处是你可以省力,不用一直站着等。


自旋锁

自旋锁就像是在排队时站着不停地走动。假设你们站成一排等待,每个人都一直走来走去,随时准备轮到自己。这种方式的好处是当轮到你时,你可以马上开始玩,因为你已经准备好了。不过缺点是你会一直走来走去,可能会有点累。


在计算机里面,当不同的程序需要访问同一个资源(比如一段数据)时,它们需要排队,避免同时使用导致错误。阻塞锁和自旋锁就是用来解决这个问题的两种方法:


阻塞锁:程序会停下来等待,直到资源可用。这就像坐下来休息,等轮到自己。

自旋锁:程序会不停地检查资源是否可用,这就像一直走来走去,随时准备使用资源。

总结一下,阻塞锁更省力,但是等待时间可能会稍长;自旋锁更快,但是会占用更多的计算资源。不同的情况下,程序会选择不同的锁来使用。


阻塞锁

阻塞锁是指当线程尝试获取锁失败时,线程进入阻塞状态,直到接收信号后被唤醒.(线程的状态包括新建、就绪、运行、阻塞及死亡)在JAVA中,能够唤醒阻塞线程的操作包括Object.notify, Object.notifyAll, Condition.signal, LockSupport.unpark。


阻塞锁在获取锁失败后,会进行阻塞,这时涉及到cpu的上下文切换。再唤醒时,也需要重新去获取cpu时间片,也需要上下文切换。


自旋锁

线程在一个循环中尝试获取锁,直到获取到锁为止。此时该线程会一直占用cpu,直到获取到锁才释放。但是由于一直在尝试获取锁中,所以执行速度会比阻塞锁快。


各自的优缺点

自旋锁

优点:


低延迟:自旋锁的等待时间通常很短,因为它只是简单地检查锁是否可用,没有涉及操作系统的调度开销。

简单实现:自旋锁的实现通常比较简单,不需要涉及复杂的操作系统机制。

适用于短时间等待:在锁定时间非常短的情况下,自旋锁可以非常高效,因为它避免了线程上下文切换的开销。

缺点:


高CPU使用率:自旋锁会不断地检查锁的状态,占用大量的CPU资源,可能导致CPU浪费。

不适合长时间等待:如果锁被占用的时间较长,自旋锁会导致大量的资源浪费,因此不适合长时间等待的场景。

可能导致优先级反转:在某些情况下,自旋锁可能会导致低优先级线程占用CPU时间,从而延迟高优先级线程的执行。

阻塞锁

优点:


节省CPU资源:阻塞锁在等待时会将线程挂起,让出CPU资源,其他任务可以继续执行。

适用于长时间等待:如果锁被占用的时间较长,阻塞锁更合适,因为线程会被挂起,直到锁可用。

减少资源竞争:通过挂起线程,阻塞锁减少了资源竞争和系统开销。

缺点:


高延迟:由于涉及操作系统的调度和线程上下文切换,阻塞锁的等待时间可能较长。

复杂实现:阻塞锁的实现需要依赖操作系统的调度机制,通常比自旋锁更复杂。

可能导致上下文切换开销:如果线程频繁地被挂起和唤醒,可能导致大量的上下文切换开销。

选择自旋锁还是阻塞锁

短时间锁定:如果预计锁定时间非常短,自旋锁可能更高效,因为避免了线程挂起和唤醒的开销。

长时间锁定:如果预计锁定时间较长,阻塞锁更合适,因为可以节省CPU资源。

总体来说,自旋锁适用于锁定时间短、锁竞争不频繁的场景,而阻塞锁更适合锁定时间较长或锁竞争较频繁的场景。根据具体的应用需求选择合适的锁类型,可以优化系统性能。


目录
相关文章
|
1月前
|
Java API
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
【多线程】乐观/悲观锁、重量级/轻量级锁、挂起等待/自旋锁、公平/非公锁、可重入/不可重入锁、读写锁
32 0
|
5月前
|
调度
线程操作:锁、条件变量的使用
线程操作:锁、条件变量的使用
30 1
|
6月前
|
Linux
Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量详解
Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量详解
194 0
Linux多线程中互斥锁、读写锁、自旋锁、条件变量、信号量详解
|
6月前
|
Linux
Linux线程同步(try锁和读写锁)
Linux线程同步(try锁和读写锁)
82 0
互斥锁、自旋锁、原子操作
互斥锁、自旋锁、原子操作
|
Linux API C++
锁、避免死锁等相关
锁、避免死锁等相关
67 0
互斥锁的死锁
互斥锁的死锁
213 1
互斥锁的死锁
|
Linux 调度 数据库
【Linux线程同步专题】一、什么是线程同步、互斥量与死锁
【Linux线程同步专题】一、什么是线程同步、互斥量与死锁
136 0
多线程中的锁
多线程中的锁有很多,但往往不是独立存在的,而是穿插共存的,接下来带你看看多线程中最常见的锁。come on!
142 2
多线程中的锁
|
Java Linux 测试技术
如何理解互斥锁、条件变量、读写锁以及自旋锁?
如何理解互斥锁、条件变量、读写锁以及自旋锁?
483 0
如何理解互斥锁、条件变量、读写锁以及自旋锁?