导读:本期聚焦于小伙伴创作的《如何通过AQS的state状态位运算设计并实现一个支持优先级的自定义共享锁》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何通过AQS的state状态位运算设计并实现一个支持优先级的自定义共享锁》有用,将其分享出去将是对创作者最好的鼓励。

在Java并发编程体系中,AbstractQueuedSynchronizer(简称AQS)是构建锁和同步器的核心基础框架,它内部维护的state状态变量是控制线程获取、释放资源的核心依据。默认情况下,AQS的state通常用于表示锁的重入次数或者剩余资源数量,但如果我们需要实现更复杂的锁逻辑,比如支持优先级的共享锁,就可以通过位运算对state的不同位段进行拆分,存储多类信息。

如何通过AQS的state状态位运算设计并实现一个支持优先级的自定义共享锁

AQS的state状态基础

AQS的state是一个volatile修饰的int类型变量,初始值为0。在独占锁模式下,state通常表示锁的重入次数,比如ReentrantLock的实现中,state大于0表示锁被占用,数值就是重入次数。而在共享锁模式下,state通常表示剩余可用的共享资源数量,比如Semaphore的实现中,state就是剩余的许可证数量。int类型有32位,我们可以将这些位拆分成不同的段,分别存储不同的信息,这就是位运算实现定制化锁的基础。

优先级共享锁的state位设计

我们要实现的优先级共享锁需要同时支持两个核心信息存储:一是当前已经获取的共享锁数量,二是当前持有锁的最高优先级。我们可以将state的32位做如下拆分:

  • 低16位(0-15位):存储当前已经获取的共享锁数量,最大值可以支持65535个共享持有
  • 高16位(16-31位):存储当前持有锁的最高优先级,优先级数值越小表示优先级越高,初始时高16位为全1表示没有持有者

对应的位运算工具方法如下:

// 从state中提取低16位的共享锁持有数量
private static int getShareCount(int state) {
    // 0xFFFF是16位全1的掩码,与state做与运算得到低16位的值
    return state & 0xFFFF;
}

// 从state中提取高16位的当前最高优先级
private static int getPriority(int state) {
    // 右移16位得到高16位的值
    return state >>> 16;
}

// 构造新的state,传入共享数量和优先级
private static int buildState(int shareCount, int priority) {
    // 低16位放共享数量,高16位放优先级
    return (priority << 16) | shareCount;
}

自定义优先级共享锁实现

我们自定义一个PriorityShareLock类,继承AQS并实现共享锁的逻辑,核心逻辑在tryAcquireShared和tryReleaseShared方法中实现。

核心属性与构造方法

我们定义优先级的范围为1-10,1是最高优先级,10是最低优先级,默认优先级为5。同时定义没有持有者时的优先级掩码为0xFFFF,也就是高16位全1的情况。

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class PriorityShareLock {
    // 优先级范围1-10,1最高,10最低
    public static final int MAX_PRIORITY = 10;
    public static final int MIN_PRIORITY = 1;
    public static final int DEFAULT_PRIORITY = 5;
    // 无持有者时的优先级,高16位全1
    private static final int NO_HOLDER_PRIORITY = 0xFFFF;

    // 内部同步器类
    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected int tryAcquireShared(int priority) {
            // 优先级参数需要校验范围
            if (priority < MIN_PRIORITY || priority > MAX_PRIORITY) {
                throw new IllegalArgumentException("优先级必须在" + MIN_PRIORITY + "到" + MAX_PRIORITY + "之间");
            }
            for (;;) {
                int currentState = getState();
                int currentShareCount = getShareCount(currentState);
                int currentPriority = getPriority(currentState);
                
                // 如果当前没有持有者,直接获取锁
                if (currentShareCount == 0) {
                    int newState = buildState(1, priority);
                    if (compareAndSetState(currentState, newState)) {
                        return 1;
                    }
                } else {
                    // 已有持有者,判断当前请求的优先级是否高于或等于当前最高优先级
                    if (priority <= currentPriority) {
                        int newShareCount = currentShareCount + 1;
                        // 更新共享数量,最高优先级保持不变
                        int newState = buildState(newShareCount, currentPriority);
                        if (compareAndSetState(currentState, newState)) {
                            return 1;
                        }
                    } else {
                        // 优先级更低,获取失败,返回负数
                        return -1;
                    }
                }
            }
        }

        @Override
        protected boolean tryReleaseShared(int arg) {
            for (;;) {
                int currentState = getState();
                int currentShareCount = getShareCount(currentState);
                int currentPriority = getPriority(currentState);
                
                if (currentShareCount == 0) {
                    // 没有持有者,释放失败
                    return false;
                }
                int newShareCount = currentShareCount - 1;
                int newPriority;
                if (newShareCount == 0) {
                    // 共享数量为0,重置优先级为无持有者状态
                    newPriority = NO_HOLDER_PRIORITY;
                } else {
                    // 共享数量不为0,优先级保持不变
                    newPriority = currentPriority;
                }
                int newState = buildState(newShareCount, newPriority);
                if (compareAndSetState(currentState, newState)) {
                    return true;
                }
            }
        }
    }

    private final Sync sync = new Sync();

    // 获取锁,使用默认优先级
    public void lock() {
        lock(DEFAULT_PRIORITY);
    }

    // 获取锁,指定优先级
    public void lock(int priority) {
        sync.acquireShared(priority);
    }

    // 释放锁
    public void unlock() {
        sync.releaseShared(1);
    }
}

核心逻辑说明

tryAcquireShared方法的逻辑如下:

  • 首先校验传入的优先级参数是否合法
  • 自旋读取当前state,拆分出共享数量和当前最高优先级
  • 如果当前没有共享持有者(共享数量为0),直接构造新的state,共享数量设为1,优先级设为当前请求的优先级,通过CAS更新state
  • 如果已有持有者,判断当前请求的优先级是否小于等于当前最高优先级(数值更小或相等),如果是则共享数量加1,优先级保持不变,CAS更新state;如果优先级更低,则返回负数表示获取失败,线程进入AQS队列等待

tryReleaseShared方法的逻辑如下:

  • 自旋读取当前state,拆分出共享数量和当前最高优先级
  • 如果共享数量为0,说明没有持有者,释放失败
  • 共享数量减1,如果减1后共享数量为0,重置优先级为高16位全1的无持有者状态;否则优先级保持不变
  • 通过CAS更新state,更新成功则返回true

使用示例

下面是一个简单的使用示例,模拟不同优先级的线程获取锁的情况:

public class PriorityShareLockTest {
    private static final PriorityShareLock lock = new PriorityShareLock();

    public static void main(String[] args) {
        // 启动3个不同优先级的线程
        new Thread(() -> {
            lock.lock(3);
            try {
                System.out.println("优先级3的线程获取锁成功");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println("优先级3的线程释放锁");
            }
        }, "priority-3-thread").start();

        new Thread(() -> {
            lock.lock(1);
            try {
                System.out.println("优先级1的线程获取锁成功");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println("优先级1的线程释放锁");
            }
        }, "priority-1-thread").start();

        new Thread(() -> {
            lock.lock(5);
            try {
                System.out.println("优先级5的线程获取锁成功");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                System.out.println("优先级5的线程释放锁");
            }
        }, "priority-5-thread").start();
    }
}

运行上述代码可以看到,优先级更高的线程(数值更小)可以成功获取锁,而优先级更低的线程如果当前已经有更高优先级的持有者,会进入等待队列,直到高优先级的持有者全部释放锁之后才能获取。

注意事项

上述实现是一个简化版本,实际使用中还需要考虑更多场景:

  • 如果需要支持优先级动态调整,还需要扩展对应的方法
  • AQS的队列是FIFO的,当前实现中低优先级线程进入队列后,即使后续有同低优先级的线程请求,也需要排队,符合公平锁的特性,如果需要非公平特性可以再做调整
  • state的位拆分需要根据实际需求调整,如果共享数量需要更大的范围,可以调整高低位的分配比例

AQSstate状态位运算自定义共享锁优先级锁并发编程修改时间:2026-07-17 02:36:37

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。