阻塞锁和自旋锁的理解

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

阻塞锁

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


自旋锁

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


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


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

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

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


阻塞锁

阻塞锁是指当线程尝试获取锁失败时,线程进入阻塞状态,直到接收信号后被唤醒.(线程的状态包括新建、就绪、运行、阻塞及死亡)在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资源。

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


目录
相关文章
|
C++ 索引 容器
c++string容器-子串获取讲解
c++string容器-子串获取讲解
716 0
|
算法 Unix 调度
【OSTEP】调度: 多级反馈队列 (MLFQ) | 优先级提升 | 饥饿问题 | 愚弄调度问题 | MLFQ 调优
【OSTEP】调度: 多级反馈队列 (MLFQ) | 优先级提升 | 饥饿问题 | 愚弄调度问题 | MLFQ 调优
845 0
|
Docker 容器
docker:记录如何在x86架构上构造和使用arm架构的镜像
为了实现国产化适配,需将原x86平台上的Docker镜像转换为适用于ARM平台的镜像。本文介绍了如何配置Docker buildx环境,包括检查Docker版本、安装buildx插件、启用实验性功能及构建多平台镜像的具体步骤。通过这些操作,可以在x86平台上成功构建并运行ARM64镜像,实现跨平台的应用部署。
8801 2
|
存储 安全
电脑怎么格式化清除所有数据
在出售、捐赠或维修电脑之前或需要处理敏感数据时,格式化硬盘并彻底清除所有数据还是很有必要的。本篇文章将详细介绍如何安全、彻底地格式化你的电脑。
电脑怎么格式化清除所有数据
|
Linux 数据安全/隐私保护
Linux命令setfacl详解
`setfacl`是Linux中用于设置文件访问控制列表的命令,提供比传统权限更细粒度的控制。它允许为特定用户或组添加、修改或删除权限,适用于多用户环境和复杂场景。常用参数包括`-m`(修改规则)、`-x`(删除规则)、`-R`(递归设置)和`-d`(设置默认ACL)。例如,`setfacl -m u:user1:rw- file.txt`给用户`user1`赋予文件`file.txt`的读写权限。记得在使用前确认文件系统支持ACL,并谨慎规划和审查权限设置。
|
SQL 算法 关系型数据库
浅析MySQL优化器统计信息
本文基于MySQL 8.0.34版本的源代码,详细介绍了MySQL中统计信息的计算和更新机制。文章首先概述了`records_per_key`统计信息在代价估计和Join Reorder算法中的重要性,接着了InnoDB统计信息的存储和计算方法,包括表级和索引级的统计信息。文章还介绍了统计信息的采样算法,特别是重要性采样在减少估计方差中的应用。此外,文章讨论了统计信息的更新时机,包括手动更新和自动更新。最后,文章简要介绍了直方图和其它统计信息,如表在内存中的占比估计,并通过实例展示了如何使用optimizer trace来分析查询优化过程。希望本文能帮助读者更好地理解MySQL的优化器。
|
UED
鸿蒙next版开发:ArkTS组件通用属性(前景色设置)
在HarmonyOS 5.0中,ArkTS提供了丰富的组件样式设置能力,包括前景色设置。本文详细解读了ArkTS中前景色设置的通用属性,并通过示例代码展示了如何使用foregroundColor属性设置组件的前景色,从而提升界面美观性和用户体验。
489 1
|
消息中间件 开发框架 .NET
.NET 8 强大功能 IHostedService 与 BackgroundService 实战
【11月更文挑战第7天】本文介绍了 ASP.NET Core 中的 `IHostedService` 和 `BackgroundService` 接口及其用途。`IHostedService` 定义了 `StartAsync` 和 `StopAsync` 方法,用于在应用启动和停止时执行异步操作,适用于资源初始化和清理等任务。`BackgroundService` 是 `IHostedService` 的抽象实现,简化了后台任务的编写,通过 `ExecuteAsync` 方法实现长时间运行的任务逻辑。文章还提供了创建和注册这两个服务的实战步骤,帮助开发者在实际项目中应用这些功能。
520 0
|
Java 数据库连接 mybatis
成功解决:文档根元素 “mapper“ 必须匹配 DOCTYPE 根 “null“
这篇文章介绍了解决MyBatis配置文件中出现的"文档根元素'mapper'必须匹配DOCTYPE根'null'"错误的步骤,通过添加正确的文件头和DOCTYPE声明到mapper.xml文件中来解决这个问题。
成功解决:文档根元素 “mapper“ 必须匹配 DOCTYPE 根 “null“
|
人机交互 调度 Windows
操作系统的概念、并发和并行的区别、操作系统的发展和分类
操作系统的概念、并发和并行的区别、操作系统的发展和分类
342 2