《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 并发编程这片江湖保驾护航,咱吃透这层关系,写起并发代码来,那也是能 "挥剑自如" 啦!不过呢,真实的它们远比咱这趣味解读复杂深邃,持续钻研、多番实践才是进阶王道哦!

相关推荐
shuair1 小时前
idea 2023.3.7常用插件
java·ide·intellij-idea
小安同学iter1 小时前
使用Maven将Web应用打包并部署到Tomcat服务器运行
java·tomcat·maven
Yvonne9782 小时前
创建三个节点
java·大数据
不会飞的小龙人3 小时前
Kafka消息服务之Java工具类
java·kafka·消息队列·mq
是小崔啊3 小时前
java网络编程02 - HTTP、HTTPS详解
java·网络·http
brevity_souls4 小时前
Spring Boot 内置工具类
java·spring boot
小钊(求职中)4 小时前
Java开发实习面试笔试题(含答案)
java·开发语言·spring boot·spring·面试·tomcat·maven
shix .4 小时前
什么是tomcat
java·tomcat
java技术小馆4 小时前
Deepseek整合SpringAI
java·spring cloud
天荒地老笑话么4 小时前
Mac安装配置Tomcat 8
java·macos·tomcat