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