如果面试官问你为什么选择使用自旋锁而不是 sleep,你该如何作答

你好,我是风一样的树懒,一个工作十多年的后端开发,曾就职京东、阿里等多家互联网头部企业。

点击下方👇关注公众号,带你一起复习后端技术,看看面试考点,补充积累技术知识,每天都为面试准备积累

文章可能会比较长,主要解析的非常详解,或涉及一些底层知识,供面试高阶难度用。可以根据自己实际理解情况合理取舍阅读


自旋锁和 sleep 是两种不同的同步机制,如果面试官直接问你为什么选择使用自旋锁而不是 sleep,通常可能是面试官设置的一个陷阱,两者应对的场景是不一样的,没有谁对谁错,一定要看当时的场景。我们先看看两张的区别:

01
自旋锁:忙等待 vs. sleep:阻塞等待


自旋锁(Spinlock):当一个线程请求锁时,如果锁已经被其他线程持有,那么该线程会在一个循环中不断检查锁的状态,直到锁变为可用。这种方式称为“自旋”。

自旋锁的核心思想是,不让线程进入阻塞状态,而是持续不断地忙等待,即使线程处于忙等待状态,CPU 会继续消耗资源来执行该线程的检查操作。

Sleep(阻塞):当一个线程请求锁时,如果锁已经被其他线程持有,线程会进入阻塞状态,等待操作系统调度该线程来继续执行。操作系统会将线程从调度队列中移除,直到锁可用时再唤醒线程。


02
效率对比


自旋锁适用场景:

  • 当锁竞争非常短暂时,使用自旋锁往往会比使用 sleep 或 wait 更高效。例如,某个线程只需要短时间的操作就能释放锁,其他线程如果进入 sleep,就可能需要等待调度,导致不必要的上下文切换和调度开销。

  • 在锁争用非常短的情况下,自旋锁可以避免线程进入操作系统调度队列,从而节省了唤醒和调度的开销。只要自旋的时间不长,自旋锁的性能往往要高于使用 sleep 或 wait 机制。

Sleep适用场景:


  • 如果锁的竞争持续时间很长,或者预期线程需要等待的时间较长,那么使用 sleep(或者其他阻塞方式)可能更合适。因为 sleep 会让线程完全放弃 CPU 资源,从而避免不必要的 CPU 计算浪费。

  • 如果多个线程竞争锁的情况较为严重且锁持有的时间较长,那么自旋锁可能导致大量的无效 CPU 占用,这时使用阻塞的 sleep 或 wait 可以让线程休眠,从而避免占用过多的 CPU 资源。


03
上下文切换开销


自旋锁的优点:自旋锁不需要发生上下文切换,线程一直处于运行状态,直到它获得锁。这意味着,线程不会进入阻塞队列,也不会被操作系统挂起,避免了上下文切换的开销。上下文切换是操作系统级别的操作,通常比较昂贵,会浪费 CPU 时间。

Sleep的缺点:线程在调用 sleep 或进入阻塞状态时,操作系统需要保存该线程的上下文并将其挂起。当锁可用时,再将线程从挂起队列中唤醒并恢复上下文,这个过程会增加额外的开销,特别是在大量线程频繁争用锁时,阻塞和唤醒的开销会更加明显。

04
响应时间与锁竞争的关系


自旋锁:适合短时间内竞争锁的场景。如果线程持有锁的时间非常短,其他线程持续自旋(忙等待)不会浪费太多的时间和资源。

Sleep:如果锁持有时间较长,使用自旋锁将导致线程频繁占用 CPU,而 sleep 使线程处于阻塞状态,释放了 CPU 资源,避免了浪费大量的 CPU 时间。这样可以减少系统的负载,适合长时间等待锁的场景。


05
系统资源占用


自旋锁:尽管自旋锁会消耗 CPU 时间,但它不涉及线程的调度和上下文切换,因此它的开销相对较小。如果自旋时间足够短,不会影响系统性能。

Sleep:会导致线程从执行队列中被移除并处于阻塞状态,直到它被唤醒。这个过程会有一定的开销,尤其在频繁切换线程时,调度和上下文切换的成本会更高。


06
自旋锁的避免过度自旋


自旋锁的缺点:
  • 如果一个线程在锁被占用时自旋的时间过长,就会浪费大量的 CPU 时间。这通常发生在锁持有的时间较长或锁竞争非常激烈的情况下。

  • 为了解决这个问题,很多实现会加入一个超时机制,限制自旋的次数,超过阈值就放弃自旋,改为进入阻塞状态,或者直接使用其他同步机制。



07
最后的小结:


自旋锁:适用于锁竞争短暂且频繁的场景,避免了上下文切换的开销。

Sleep/阻塞:适用于锁竞争激烈或者持锁时间较长的情况,避免了线程持续占用 CPU 的情况。

一定要基于场景来进行作答,不要被误导了

今天的内容就分享到这儿,喜欢的朋友可以关注,点赞。有什么不足的地方欢迎留言指出,您的关注是我前进的动力!

END


扫码关注

一起积累后端知识
不积跬步,无以至千里
不积小流,无以成江海

喜欢此内容的人还喜欢

谈谈id那些事(五)——美团的 Leaf 的ID生成


一个阿里二面面试官必问的问题


Lambda表达式说爱你不容易


分享面试:mysql数据库索引失效的情况


Spring-Boot中一个不起眼的好工具StopWatch