Java自定义互斥锁的实现方法示例

 更新时间:2025年11月15日 12:00:55   作者:va学弟  
在多线程编程中互斥锁是确保共享资源安全访问的重要机制,这篇文章主要介绍了Java自定义互斥锁实现的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

今天我们利用AQS实现一个基础的自定义的互斥锁。

1.AQS

AbstractQueueSynchronizer,简称AQS,是 Java 并发编程的核心基础框架,它为各种同步器(如ReentrantLockSemaphoreCountDownLatch等)提供了统一的底层实现,解决了并发场景中线程的同步与协作问题。它的设计思想可以概括为:用一个 volatile 状态变量控制同步逻辑,用一个 CLH 队列管理等待线程。下面我们简单介绍一下其核心内容。

一、AQS 的核心结构

AQS 的核心由两部分组成:同步状态(State) 和等待队列(CLH 队列)

1.同步状态(State)

        定义:AQS 通过 private volatile int state 变量来维护同步状态,该状态值的具体语义由实现类(子类)自行定义。以 ReentrantLock 为例:

  • state = 0 表示锁未被占有
  • state > 0 表示锁被持有,数值代表当前线程的重入次数(线程每次获取锁时 state 递增,释放锁时 state 递减)

2. 等待队列(CLH 队列)

当线程获取锁失败时,AQS 会将线程封装成一个节点(Node) 加入等待队列,这个队列是一个双向链表,基于 CLH(Craig, Landin, and Hagersten)锁队列改进而来。

二、AQS 的核心机制

AQS(AbstractQueuedSynchronizer)的核心机制分为独占式共享式两种同步模式,分别对应不同的锁获取与释放逻辑。

1.独占式模式(Exclusive)

独占式模式下,同一时刻只有一个线程能获取锁(如 ReentrantLock)。其核心流程如下:

获取锁(acquire)

调用 tryAcquire(int arg):由子类实现,尝试获取锁(如检查 state 是否为 0,并通过 CAS 修改 state)。若成功,直接返回;若失败,进入后续步骤。

调用 addWaiter(Node.EXCLUSIVE):将当前线程封装为独占模式的 Node 节点,并加入等待队列尾部。

调用 acquireQueued(Node node, int arg):节点在队列中自旋等待,直到获取锁或被取消。在此过程中:

  • 节点检查前驱节点是否为头节点:若是,则再次尝试 tryAcquire;若成功,将自己设为新头节点。
  • 若前驱节点状态不是 SIGNAL,则将其状态改为 SIGNAL(确保前驱释放锁时能唤醒自己)。
  • 若获取失败,通过 LockSupport.park(this) 阻塞当前线程。

释放锁(release)

调用 tryRelease(int arg):由子类实现,尝试释放锁(如修改 state 的值)。
若成功,检查头节点的状态:若为 SIGNAL,则调用 unparkSuccessor(Node node) 唤醒后继节点。
被唤醒的后继节点会重新进入自旋,尝试获取锁。

2.共享式模式(Shared)

共享式模式下,同一时刻多个线程可获取锁(如 SemaphoreCountDownLatch)。其核心流程如下:

获取锁(acquireShared)

调用 tryAcquireShared(int arg):由子类实现,尝试获取共享锁(如检查 state 是否大于 0)。

若返回值 >=0(成功),直接返回;若 <0(失败),进入后续步骤。

调用 doAcquireShared(int arg):将线程封装为共享模式的 Node 节点,加入等待队列并自旋等待。

与独占式不同,共享模式下,一个节点获取锁后可能会唤醒后续所有共享节点(如 Semaphorerelease 会释放多个许可)。

释放锁(releaseShared)

调用 tryReleaseShared(int arg):由子类实现,尝试释放共享锁(如增加 state 的值)。
若成功,唤醒后续等待的共享节点。

三、AQS 的核心方法

AQS 基于模板方法模式设计,将同步器的核心逻辑分为两部分:父类定义的固定流程(模板方法)和子类实现的定制逻辑(钩子方法)。

1.模板方法(AQS 已实现)

独占式锁操作

  • acquire(int arg):阻塞式获取独占锁,忽略中断。
  • release(int arg):释放独占锁,唤醒后续线程。
  • tryAcquireNanos(int arg, long nanosTimeout):支持超时和中断的独占锁获取。

共享式锁操作

  • acquireShared(int arg):阻塞式获取共享锁。
  • releaseShared(int arg):释放共享锁,唤醒等待线程。
  • tryAcquireSharedNanos(int arg, long nanosTimeout):支持超时和中断的共享锁获取。

辅助功能

  • getQueuedThreads():获取等待队列中的线程集合。

2.钩子方法(子类需重写)

独占式锁实现

  • tryAcquire(int arg):定义独占锁的获取逻辑,返回成功状态。
  • tryRelease(int arg):定义独占锁的释放逻辑,返回成功状态。

共享式锁实现

  • tryAcquireShared(int arg):定义共享锁的获取逻辑,返回剩余可用资源数。
  • tryReleaseShared(int arg):定义共享锁的释放逻辑,返回是否完全释放。

条件变量支持

  • isHeldExclusively():判断当前线程是否独占持有锁,用于实现 Condition。

通过重写钩子方法,子类可灵活实现公平/非公平锁、读写锁等同步机制,而 AQS 负责队列管理、阻塞唤醒等底层操作。

2.自定义互斥锁

MLock通过静态内部类Sync继承 AQS,并重写关键方法,实现了一个独占式非重入锁(同一线程不能重复获取锁)。

public class MLock {
    private Sync sync = new Sync();
    private static class Sync extends AbstractQueuedLongSynchronizer{

        @Override
        protected boolean tryAcquire(long arg) {
            //利用CAS算法把state变量改成1
            if(compareAndSetState(0,arg)){
                //操作成功后把当前线程设置成独占
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;

        }

        @Override
        protected boolean tryRelease(long arg) {
            //清空当前线程
            setExclusiveOwnerThread(null);
            setState(arg);
            return true;

        }

        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;

        }
    }

    //加锁
    public void lock(){
        sync.acquire(1);
    }
    //释放锁
    public void unlock(){
        sync.release(0);
    }

}

一、Sync内部类(AQS 子类)

Sync 作为锁的核心实现,重写了 AQS 中的 3 个关键方法和 1 个条件变量方法:

1.tryAcquire(int arg) - 独占锁获取

执行逻辑:当 state 为 0(未锁定状态)时,通过 CAS 操作将其置为 1,并记录当前线程为锁持有者

2.tryRelease(int arg) - 独占锁释放

执行逻辑:先清除锁持有者线程信息,再将 state 重置为 0,允许其他线程获取锁

3.isHeldExclusively() - 独占锁状态检查

执行逻辑:通过检查 state 是否为 1 来判断锁是否被占用(注:简化实现,实际还需验证持有者线程)

4.newCondition() - 条件变量创建

功能说明:提供基于锁的等待/通知机制,支持 await() 和 signal() 等操作

二、MLock对外提供的方法

这些方法是锁的使用接口,内部通过调用Sync(AQS)的方法实现:

  • lock():获取锁(阻塞式)

    逻辑:如果tryAcquire成功(获取锁),直接返回;否则,当前线程会被加入 AQS 的等待队列,进入阻塞状态,直到被唤醒并成功获取锁

  • tryLock():尝试获取锁(非阻塞式)                                                                                     
    逻辑:仅尝试一次获取锁,成功返回true,失败立即返回false,不会阻塞。

  • unlock():释放锁

    逻辑:释放锁后,AQS 会唤醒等待队列中的一个线程,让其尝试获取锁。

  • newCondition():获取条件变量用于线程间的协作(如生产者 - 消费者模型),基于当前锁实现等待 / 通知。

总结 

到此这篇关于Java自定义互斥锁实现方法的文章就介绍到这了,更多相关Java自定义互斥锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java获取中文拼音首字母的实例

    java获取中文拼音首字母的实例

    下面小编就为大家带来一篇java获取中文拼音首字母的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • SpringBoot项目运行jar包启动的步骤流程解析

    SpringBoot项目运行jar包启动的步骤流程解析

    这篇文章主要介绍了SpringBoot项目运行jar包启动的步骤流程,本文分步骤通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-07-07
  • SpringMVC @ResponseBody 415错误处理方式

    SpringMVC @ResponseBody 415错误处理方式

    这篇文章主要介绍了SpringMVC @ResponseBody 415错误处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Quarkus改造Pmml模型项目异常记录及解决处理

    Quarkus改造Pmml模型项目异常记录及解决处理

    这篇文章主要为大家介绍了Quarkus改造Pmml模型项目是遇到的异常记录以及解决方法,有需要的同学可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-02-02
  • springboot 打包部署 共享依赖包(分布式开发集中式部署微服务)

    springboot 打包部署 共享依赖包(分布式开发集中式部署微服务)

    这篇文章主要介绍了springboot 打包部署 共享依赖包(分布式开发集中式部署微服务)的相关资料,非常不错,具有参考借鉴价值,需要的的朋友参考下吧
    2017-06-06
  • springboot动态定时任务的实现方法示例

    springboot动态定时任务的实现方法示例

    这篇文章主要给大家介绍了关于springboot动态定时任务的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Spring Boot Admin 添加报警提醒和登录验证功能的具体实现

    Spring Boot Admin 添加报警提醒和登录验证功能的具体实现

    报警提醒功能是基于邮箱实现的,当然也可以使用其他的提醒功能,如钉钉或飞书机器人提醒也是可以的,但邮箱报警功能的实现成本最低,所以本文我们就来看邮箱的报警提醒功能的具体实现
    2022-01-01
  • SpringBoot整合MQTT并实现异步线程调用的问题

    SpringBoot整合MQTT并实现异步线程调用的问题

    这篇文章主要介绍了基于SpringBoot通过注解实现对mqtt消息处理的异步调用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • Spring Boot接口幂等插件用法示例解析

    Spring Boot接口幂等插件用法示例解析

    这篇文章主要介绍了Spring Boot接口幂等插件用法示例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • spring boot实现图片上传和下载功能

    spring boot实现图片上传和下载功能

    这篇文章主要为大家详细介绍了spring boot实现图片上传和下载功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02

最新评论