当前位置: 首页 > news >正文

几种常用锁

1. sync (Synchronized - 同步关键字)

  • 本质:它是 Java 语言内置的一个关键字 (synchronized),是一种隐式锁(Implicit Lock)。
  • 作用:提供一种简单的、自动的锁管理方式,用于标记一个代码块或方法,确保同一时间只有一个线程能够执行这段代码。
  • 工作原理
    1. 当一个线程进入一个被 synchronized 修饰的代码块或方法时,它会尝试获取与之关联的监视器锁(Monitor Lock)
    2. 如果锁未被占用,线程获得锁并执行代码。
    3. 如果锁已被其他线程占用,该线程会进入阻塞状态,等待锁被释放。
    4. 当线程执行完毕(正常退出或抛出异常),它会自动释放锁。
  • 关键特性
    • 可重入性:同一线程可以多次进入同一个 synchronized 方法或代码块(因为锁的计数器会递增)。
    • 自动释放:锁会在代码块执行完毕后自动释放,即使发生了异常也会释放(通过 finally 块机制)。
    • 隐式监视器:锁对象通常是 this 或指定的对象实例/类对象(对于静态方法)。
  • 优点:语法简洁,使用方便,由 JVM 自动管理锁的获取和释放,不易遗漏。
  • 缺点:灵活性较差(只能整块加锁)、性能相对较低(早期版本)、难以进行精细化控制(如超时获取锁、公平性设置)。

2. ReentrantLock (可重入锁)

  • 本质:它是 Java java.util.concurrent.locks 包下的一个显式锁(Explicit Lock) 类。
  • 作用:提供比 synchronized 更丰富、更灵活的锁功能。
  • 工作原理
    1. 你需要显式地创建一个 ReentrantLock 实例。
    2. 通过调用 lock() 方法获取锁。
    3. 在 finally 块中调用 unlock() 方法释放锁(这一点非常重要,否则会导致死锁!)。
  • 关键特性
    • 可重入性:同上,支持同一线程多次获取锁。
    • 显式控制:需要手动获取和释放锁,灵活性高。
    • 公平性:可以在构造函数中指定锁的公平性(true 表示公平锁,false 表示非公平锁,默认是非公平锁)。
    • 中断响应:提供了 lockInterruptibly() 方法,允许在等待锁的过程中响应中断。
    • 超时获取:提供了 tryLock(long time, TimeUnit unit) 方法,允许在指定时间内尝试获取锁,超时则返回 false。
    • 条件变量:可以配合 Condition 接口使用,实现更复杂的线程间协作(类似 Object.wait() / notify() 但更强大)。
  • 优点:功能强大,灵活可控,性能在某些场景下优于 synchronized(尤其是在 JDK 1.6 之后,两者差距缩小,但 ReentrantLock 仍有优势)。
  • 缺点:使用稍微繁琐,需要手动释放锁,容易忘记在 finally 块中释放导致死锁。

3. Volatile (易失性变量)

  • 本质:它是一个变量修饰符,不是一个锁!但它与并发控制密切相关,常被称为“轻量级的同步机制”。
  • 作用:确保对一个变量的修改,对其他线程立即可见(可见性);禁止指令重排序(有序性)。
  • 工作原理
    1. 可见性:当一个线程修改了一个 volatile 变量的值,这个新值会立即强制刷写到主内存中。其他线程在读取这个变量时,会从主内存中读取最新的值,而不是使用本地缓存中的旧值。
    2. 有序性volatile 变量的读写操作具有“happens-before”关系,禁止编译器和处理器对其进行重排序(除了必要的重排序以保证单线程语义)。
  • 关键特性
    • 不保证原子性volatile 不能保证复合操作的原子性(例如 i++)。它只保证单个读/写操作的原子性(对于大多数基本类型和引用类型)。
    • 轻量级:相比锁,volatile 的开销要小得多。
  • 适用场景:主要用于标记某个状态(如 boolean flag),或者作为状态标志位,指示某个事件的发生。不适合用作计数器或其他需要原子更新的数值。
  • 优点:开销小,保证了可见性和有序性。
  • 缺点:不能保证原子性,应用场景有限。

4. CAS (Compare-And-Swap - 比较并交换)

  • 本质:它是一种硬件级别的原子操作指令,是许多无锁算法的基础。Java 通过 sun.misc.Unsafe 类或 java.util.concurrent.atomic 包下的原子类间接提供了 CAS 支持。
  • 作用:在不使用锁的情况下,实现原子性的变量更新。
  • 工作原理
    1. 有三个参数:内存地址 V,期望值 A,新值 B。
    2. CPU 会比较内存地址 V 上的值是否等于期望值 A。
    3. 如果相等,就把 V 上的值替换为新值 B,并返回 true
    4. 如果不相等,不做任何操作,并返回 false
  • 关键特性
    • 原子性:整个过程是原子的,要么全部完成,要么全部不完成。
    • 无锁:不需要加锁,避免了线程阻塞和上下文切换的开销。
    • 乐观锁:属于乐观锁的实现机制。它假设冲突很少发生,所以先尝试更新,失败了再重试(自旋)。
  • 优点:性能极高,避免了锁的开销。
  • 缺点
    • ABA 问题:如果一个值从 A 变成 B 又变回 A,CAS 会误以为它从未被修改过。可以通过添加版本号或时间戳来解决。
    • 自旋消耗 CPU:如果 CAS 操作一直失败(竞争激烈),会一直自旋,消耗 CPU 资源。
    • 只能保证一个共享变量的原子操作:对于多个共享变量,CAS 无法直接保证原子性,需要借助其他手段(如 AtomicReferenceFieldUpdater)。

总结对比

特性sync (Synchronized)ReentrantLockVolatileCAS
类型关键字(隐式锁)类(显式锁)变量修饰符原子操作指令
主要作用保证原子性、可见性、有序性提供更丰富的锁功能保证可见性、有序性实现原子性更新
原子性✅ (代码块/方法级)✅ (代码块级)❌ (仅单次读写)✅ (单变量)
可见性❌ (需配合 volatile)
有序性❌ (需配合 volatile)
可重入
公平性❌ (非公平)✅ (可选)
中断响应
超时获取
条件变量❌ (仅 wait()/notify())
开销较高较高(但可控性强)很低很低
复杂性中等高(实现层面)
典型用途通用同步需求需要精细控制的同步需求状态标志位无锁算法、原子变量更新

一句话概括:

  • 用 sync 或 ReentrantLock 来保护临界区
  • 用 volatile 来保证单个变量的可见性和有序性。
  • 用 CAS 来实现原子性更新,是构建无锁数据结构的基石。

文章转载自:

http://Arnrejze.Lgcqj.cn
http://QfuBoyyO.Lgcqj.cn
http://glMR59uj.Lgcqj.cn
http://Ww5529dM.Lgcqj.cn
http://O4EQxCSQ.Lgcqj.cn
http://FwlcaP6h.Lgcqj.cn
http://m4wzSDZU.Lgcqj.cn
http://3o9xPx48.Lgcqj.cn
http://LGIoAoBB.Lgcqj.cn
http://XSmWpMwz.Lgcqj.cn
http://YEftj7FO.Lgcqj.cn
http://1tZVJ3b9.Lgcqj.cn
http://kRXAu6zZ.Lgcqj.cn
http://3K3KNUie.Lgcqj.cn
http://0oXgv364.Lgcqj.cn
http://QxSmW7hQ.Lgcqj.cn
http://5X0HZgF9.Lgcqj.cn
http://R2Afjz93.Lgcqj.cn
http://2yzw3FHu.Lgcqj.cn
http://ie7oikuG.Lgcqj.cn
http://l5VX7h9M.Lgcqj.cn
http://C0UCttwR.Lgcqj.cn
http://z3vu7r8A.Lgcqj.cn
http://uLP23bw2.Lgcqj.cn
http://OUbf0c0V.Lgcqj.cn
http://BoM3jIkY.Lgcqj.cn
http://p6FcDL4R.Lgcqj.cn
http://iuMd1MWF.Lgcqj.cn
http://bGS3XCg0.Lgcqj.cn
http://13VnhZjc.Lgcqj.cn
http://www.dtcms.com/a/378671.html

相关文章:

  • android13修改WiFi扫描二维码识别识别成功率不高的问题
  • params和body传参讲解
  • 单片机学习笔记
  • 图卷积神经网络(GCN)学习笔记
  • MySQL执行过程中如何选择最佳的执行路径
  • 牛客周赛 Round 108(思维、位运算、DP、SOSDP)
  • 插槽 el-input 数据双向 绑定失效 响应式更新失败
  • 代码随想录算法训练营第58天 | 拓扑排序精讲、dijkstra(朴素版)精讲
  • 揭秘KafkaStreams 线程缓存:NamedCache深度解析
  • 中标麒麟7.4部署gitlab-runner
  • Shopify指纹手机矩阵:无限扩店,横扫FB/GG广告封号风险
  • react context如何使用
  • npm是什么?优缺点又是什么?
  • ubuntu24.04+5070ti训练yolo模型(2)
  • [SQL]查询SSMS当前连接数据库列表
  • 乾博绝缘监测仪为水泥厂安全生产护航
  • JVM(jdk1.8) 实战
  • 设计模式(C++)详解—工厂方法模式(2)
  • 自动化运维实践:SaaS系统Nginx配置文件自动化运维脚本详解
  • 3D模型快速混沌加密matlab完整代码
  • 敏捷实践指南(中文版):章节梳理/主要知识体系和知识点
  • 第一章 ELK Stack基础概念与架构
  • GraphQL RPC 与通用索引器公测介绍:为 Sui 带来更强大的数据层
  • ShardingSphere 分库分表技术实现与实战案例
  • Docker 部署 MongoDB:单节点与副本集的最佳实践
  • OCR 识别表现好坏离不开什么?
  • 阿里云ACA认证[特殊字符]阿里云ACP认证
  • 计算机网络实验00---环境准备
  • 【路由交换技术】基于eNSP的多子网路由互通实验:从配置到验证的全流程指南
  • 【Python】Python解决阿里云DataWorks导出数据1万条限制的问题