《Lock 锁与 AQS 的 “家族秘史”:继承那些事儿,代码来揭秘》

公众号:装睡鹿先生

嘿,各位编程江湖里的 "大侠" 们!今天咱不玩虚的,要唠唠 Java 并发编程里那神秘又紧密的 "家族关系"------Lock 锁和 AQS(AbstractQueuedSynchronizer)之间的继承渊源,就像揭开武林中两大高手背后不为人知的 "师承纽带",还会搬出代码这 "神奇法宝",用一场趣味 "代码戏法" 把事儿说得明明白白,走着!

一、AQS:神秘的 "武林宗师"

想象咱这 Java 并发编程的江湖,是个卧虎藏龙、规矩森严的 "武林世界"。这 AQS 呀,就如同一位隐居深山、身怀绝世神功的 "武林宗师",平日里不显山不露水,可肚子里全是 "独家秘籍",掌控着多线程抢夺资源这场 "混战" 的 "生杀大权"。

它有两门 "绝世神功" 最为出名,一门是对 "资源状态" 的精妙把控,就像守着一座藏满珍宝的山洞,有个神秘的 "魔力计数器"(state 变量)时刻记录着珍宝是否被人拿走、被谁拿走、拿走多少。要是珍宝(资源)还在洞里安然无恙,"魔力计数器" 显示 "0",一旦有大侠(线程)身手敏捷抢到手,这计数器就 "咔咔" 变动,标记归属,而且它用神奇的 "原子魔法"(compareAndSetState 操作,利用底层硬件指令保障多线程下数据修改安全)来更新状态,绝不允许混乱。

另一门神功呢,是一套神奇的 "排队阵法",倘若来抢珍宝的大侠太多,一时半会儿抢不到的,就被宗师引入一个无形却有序的 "长龙队列"(同步队列),大侠们在这儿按先来后到站好,眼巴巴等着前面人用完珍宝归还,再依次上前尝试,期间还能用 "歇脚小亭阵法"(条件队列,配合 Condition 接口施展),让大侠在特定条件未满足时先去亭子里打个盹、歇会儿,条件一好立马 "满血复活" 重新排队抢宝,端的是精妙绝伦、有条不紊。

咱瞅瞅这 "宗师" 大概模样(极简模拟,领会精神,真实的它在 JDK 里更复杂高深):

scala 复制代码
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

// 咱这简易版"宗师",叫 MiniAQS,看着朴素,关键"神韵"不缺
class MiniAQS extends AbstractQueuedSynchronizer {
    // 尝试抢宝(获取资源),大侠靠近山洞时的考验
    @Override
    protected boolean tryAcquire(int arg) {
        int state = getState();
        if (state == 0 && compareAndSetState(0, arg)) {
            // 珍宝没主(state 为 0),且凭"原子魔法"占为己有,标记归属
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }

    // 归还珍宝(释放资源),用完得还,江湖规矩
    @Override
    protected boolean tryRelease(int arg) {
        if (Thread.currentThread()!= getExclusiveOwnerThread()) {
            throw new IllegalMonitorStateException();
        }
        setState(0);
        setExclusiveOwnerThread(null);
        return true;
    }
}

二、Lock 锁:得意 "门徒" 闯江湖

这 Lock 锁呢,就像是 AQS "武林宗师" 精心调教出来、闯荡江湖的得意 "门徒",身负师父真传,去应对各种复杂并发场景,把师父那套绝学发扬光大。

且看 "ReentrantLock"(可重入锁)这员大将,它头戴 "公平 / 不公平锁" 的双色帽,在江湖中各显神通。在它 "骨子" 里,紧紧依附着 AQS,像个孝顺徒弟时刻遵循师父教诲。从代码里瞧,那继承关系一目了然:

java 复制代码
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.ReentrantLock;

// 咱把 ReentrantLock "解剖"一番,深挖它和 AQS 的"血缘"
class MyReentrantLockAnalysis {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        // 瞅瞅,这锁一创建,背后就默默关联上了 AQS 的"影子力量"
        AbstractQueuedSynchronizer aqsInside = getAQSFromLock(lock);
        System.out.println("ReentrantLock 内部关联的 AbstractQueuedSynchronizer:" + aqsInside);
    }

    // 这是个"探秘"小法术,挖出锁背后的 AQS 实例(简化示意,真实获取更复杂但原理相似)
    private static AbstractQueuedSynchronizer getAQSFromLock(ReentrantLock lock) {
        try {
            java.lang.reflect.Field syncField = ReentrantLock.class.getDeclaredField("sync");
            syncField.setAccessible(true);
            return (AbstractQueuedSynchronizer) syncField.get(lock);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

在这段 "探秘代码" 里,咱们像个精明的 "江湖密探",用点反射小技巧(别担心,只是为了看清内部关联,实际开发慎用哦),把 ReentrantLock 藏在 "黑袍" 下的 AQS "真身" 给揪了出来,明明白白展示它俩这紧密的继承纽带 ------ReentrantLock 内部有个专门负责同步管理的 "小管家"(sync 对象),而这 "小管家" 正是继承自 AQS 这位 "宗师",靠着师父传下的资源管理(像 state 变量把控锁状态)、排队调度(同步队列与条件队列玩法)等 "秘籍",在并发江湖里为线程大侠们安排 "抢锁大战",保证锁的获取、持有、释放稳稳当当,不闹出 "多线程争抢一锅粥" 的乱象。

再说说它咋用师父的功夫,比如抢锁时(lock 方法调用),就是借助 AQS 的 "排队阵法",大侠们(线程)有序竞争,成功拿到锁就标记独占(基于 AQS 的 state 更新);释放锁时(unlock 方法),按规矩重置状态、唤醒后续等待大侠,活脱脱把 AQS 的绝学演绎得精彩绝伦,在并发战场立下赫赫战功,让多线程编程这片 "江湖" 有了安稳秩序。

三、"家族联手" 镇并发

当咱们在代码江湖里写下这么一段:

csharp 复制代码
import java.util.concurrent.locks.ReentrantLock;

public class LockAndAQSAdventure {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                lock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " 抢到锁啦,正在'密室'(临界区)办事!");
                    // 模拟办事过程,比如操作共享资源啥的,这里简单休眠会儿
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                    System.out.println(Thread.currentThread().getName() + " 用完锁啦,拱手让出!");
                }
            }).start();
        }
    }
}

瞧这阵仗,五个 "线程大侠" 气势汹汹冲向 "密室"(临界区,共享资源操作处),都想抢那把 "ReentrantLock" 锁进门办事。多亏了背后 AQS "宗师" 的深厚功底、精密调度,大侠们在锁前乖乖排队,依次尝试,拿到锁的安心办事,用完立马归还,循环往复,整个过程流畅有序,像一场配合默契的 "接力赛",完美诠释 Lock 锁依托 AQS 在并发江湖里 "定分止争" 的强大能耐,把这 "家族传承" 发挥到极致,让咱编程之路少些 "多线程乌龙",多些安稳高效,是不是妙得很呐!

所以说,Lock 锁与 AQS 的继承关系,就像武林中名师高徒携手镇场子,靠着深厚底蕴与精妙配合,为 Java 并发编程这片江湖保驾护航,咱吃透这层关系,写起并发代码来,那也是能 "挥剑自如" 啦!不过呢,真实的它们远比咱这趣味解读复杂深邃,持续钻研、多番实践才是进阶王道哦!

相关推荐
茂桑9 分钟前
Idea集成AI:CodeGeeX开发
java·ai·intellij-idea
jackson凌23 分钟前
【Java学习笔记】运算符
java·笔记·学习
追逐时光者32 分钟前
6种流行的 API 架构风格,你知道几种?
后端
咸鱼求放生36 分钟前
网络请求只到前端页面接口报200并到不到后端接口
java
只会AI搜索得coder43 分钟前
sqlite3 sqlcipher加密,解密,集成springboot,读取sqlcipher加密工具
java·spring boot·sqlite
小麦果汁吨吨吨1 小时前
Flask快速入门
后端·python·flask
kinlon.liu1 小时前
SpringBoot整合Redis限流
spring boot·redis·后端
爱的叹息1 小时前
微服务的服务调用详解以及常见解决方案对比
微服务·云原生·架构
cg50171 小时前
Spring Boot 中的自动配置原理
java·前端·数据库
纪元A梦2 小时前
华为OD机试真题——跳格子3(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
java·javascript·c++·python·华为od·go·华为od机试题