网站首页 > java教程 正文
公平锁和非公平锁是并发编程中两种常见的锁策略,理解它们的区别需要结合生活场景和底层原理来讲解。
一、通俗比喻理解
1. 公平锁
场景:银行排队叫号机。假设银行有10个窗口,但每次只开放1个窗口。所有客户必须按取号顺序办理业务,即使窗口空闲时也必须等待叫号。
特点:先来的人一定先被服务,严格按顺序。
2. 非公平锁
场景:地铁抢座位。地铁到站时,所有等待的乘客一拥而上,谁挤得快谁先坐,不管谁先到站台。
特点:后来的可能“插队”成功,效率更高但可能不公平。
二、技术原理对比
1. 公平锁
当一个线程尝试获取锁时,会先检查等待队列(AQS中的CLH队列)是否有其他线程在等待。如果队列为空,或当前线程是队列的第一个,则获取锁成功。如果队列中有其他线程,则当前线程进入队列尾部排队。
2. 非公平锁
线程尝试获取锁时,直接通过CAS(Compare-And-Swap)抢占锁,不检查队列是否有等待线程。如果锁空闲,立即获取成功。如果锁被占用,再进入队列排队。
三、核心区别总结
特性 | 公平锁 | 非公平锁 |
顺序性 | 严格按请求顺序分配锁 | 允许“插队”,后申请的线程可能先获取锁 |
性能 | 吞吐量低(需要频繁线程切换) | 吞吐量高(减少线程切换) |
饥饿问题 | 不会出现线程饥饿 | 可能发生线程饥饿 |
实现复杂度 | 更复杂(需维护队列顺序) | 更简单(直接CAS抢锁) |
四、应用场景
1. 公平锁适用场景
需要严格顺序性:例如订单系统,确保先下单的用户先处理,避免资源被长时间占用。
防止线程饥饿:在任务执行时间差异大的场景(如长任务和短任务混合),避免短任务被长任务“饿死”。
2. 非公平锁适用场景
高吞吐需求:例如Web服务器的并发请求处理,减少线程切换开销,提升性能。
锁持有时间短:如果线程释放锁后很快再次申请锁(如自旋锁),非公平锁能减少排队等待时间。
五、性能差异原因
公平锁的额外开销:每次获取锁时需检查队列状态(hasQueuedPredecessors()),且唤醒线程需要从队列头部开始,涉及更多上下文切换。
非公平锁的优势:线程释放锁后,新来的线程可能直接获取锁,避免唤醒队列中线程的开销(减少线程切换)。
六、实战建议
默认选择非公平锁:如Java的ReentrantLock默认是非公平锁,因为大多数场景吞吐量更重要。
仅在必要时用公平锁:当业务明确要求顺序性(如交易系统、排队系统)时,才使用公平锁。
猜你喜欢
- 2025-06-23 Java阻塞队列:LinkedTransferQueue
- 2025-06-23 Java面试题-锁的膨胀升级过程(锁的机制升降级)
- 2025-06-23 Java中CurrentHashMap的使用原理?
- 2025-06-23 Java并发锁机制和Atomic原理解析(java并发的时候常用的处理方式)
- 2025-06-23 「Java多线程」内置锁(Synchronized)的前世今生
- 2025-06-23 Java 面试题:乐观锁和悲观锁的理解及如何实现,有哪些实现方式?
- 2025-06-23 万字详文:腾讯高可用、高性能 ZooKeeper 源码和实践揭秘
- 2025-06-23 ReentrantLock源码解析:ReentrantLock 的实现原理与 AQS 机制
- 2025-06-23 Java面试题整理:紧跟2025年面试趋势
- 2025-06-23 面试官:说一下 synchronized 锁机制原理 与 Lock 锁机制
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)