【JUC】公平锁与非公平锁

发布时间:2026/10/14 5:09:23
【JUC】公平锁与非公平锁 在 Java 多线程中公平锁和非公平锁是ReentrantLock提供的两种锁获取策略核心区别在于多个线程竞争锁时是否严格按照“先来后到”的顺序获取锁。下面从原理、实现、优缺点和代码示例几个方面来讲。一、基本概念1. 公平锁Fair Lock多个线程按照申请锁的顺序来获取锁先到先得。线程会进入一个 FIFO 队列排队只有队首的线程才能获取锁。新来的线程不能插队即使锁刚好空闲也要先看队列里有没有等待的线程。2. 非公平锁Nonfair Lock不保证顺序允许插队。新来的线程可以直接尝试 CAS 抢锁如果抢到了就直接执行不管队列里有没有等待的线程。抢不到再进入队列等待。二、源码层面的区别ReentrantLock内部通过Sync抽象类实现有两个子类publicclassReentrantLockimplementsLock{privatefinalSyncsync;abstractstaticclassSyncextendsAbstractQueuedSynchronizer{// ...}// 非公平锁staticfinalclassNonfairSyncextendsSync{...}// 公平锁staticfinalclassFairSyncextendsSync{...}}非公平锁的加锁逻辑简化finalvoidlock(){// 直接 CAS 抢锁不管有没有队列if(compareAndSetState(0,1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);// 抢不到再走正常流程}tryAcquire中也不会检查队列protectedfinalbooleantryAcquire(intacquires){returnnonfairTryAcquire(acquires);}公平锁的加锁逻辑protectedfinalbooleantryAcquire(intacquires){finalThreadcurrentThread.currentThread();intcgetState();if(c0){// 关键先判断队列中是否有前驱节点if(!hasQueuedPredecessors()compareAndSetState(0,acquires)){setExclusiveOwnerThread(current);returntrue;}}// ... 可重入逻辑}hasQueuedPredecessors()是公平锁的核心如果队列里已经有线程在等就不抢乖乖排队。三、公平锁 vs 非公平锁对比维度公平锁非公平锁获取顺序严格 FIFO允许插队吞吐量较低较高线程饥饿不会可能理论上上下文切换较多较少实现复杂度略高略低默认策略否是ReentrantLock 默认非公平为什么非公平锁吞吐量更高因为公平锁每次都要唤醒队首线程涉及线程切换用户态→内核态开销大。而非公平锁允许刚释放锁的线程或新来的线程立刻抢到锁减少了线程唤醒和切换的次数。注意非公平锁虽然可能“插队”但一旦进入队列仍然是 FIFO 的只是新来的线程有机会在入队前抢到锁。四、代码示例importjava.util.concurrent.locks.ReentrantLock;publicclassFairLockDemo{// true 表示公平锁false 表示非公平锁privatestaticfinalReentrantLockfairLocknewReentrantLock(true);privatestaticfinalReentrantLockunfairLocknewReentrantLock(false);publicstaticvoidmain(String[]args){testLock(fairLock,公平锁);System.out.println(----------);testLock(unfairLock,非公平锁);}privatestaticvoidtestLock(ReentrantLocklock,Stringname){Runnabletask()-{for(inti0;i2;i){lock.lock();try{System.out.println(name - Thread.currentThread().getName() 获取锁);}finally{lock.unlock();}}};for(inti0;i5;i){newThread(task,线程-i).start();}try{Thread.sleep(1000);}catch(InterruptedExceptione){}}}公平锁下输出顺序基本是线程-0、线程-1、线程-2...轮转非公平锁下顺序可能混乱某些线程会连续获取多次。五、其他相关点1. synchronized 是公平锁吗不是。synchronized是非公平的且不支持设置为公平锁。它的锁获取策略由 JVM 实现偏向锁、轻量级锁、重量级锁都偏向于性能不保证公平。2. 读写锁的公平性ReentrantReadWriteLock也支持公平/非公平newReentrantReadWriteLock(true);// 公平3. 什么时候用公平锁业务要求严格按顺序执行比如某些资源调度。需要避免线程饥饿的场景。大多数情况下优先用非公平锁默认性能更好。六、一句话总结公平锁按排队顺序获取锁避免饥饿但性能较低非公平锁允许插队吞吐量高但可能造成线程饥饿。ReentrantLock默认是非公平锁通过构造函数new ReentrantLock(true)可开启公平模式。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询