基于AQS实现自定义同步类
Mutex(互斥锁)
Mutex是一个不可重入的互斥锁实现。锁资源(AQS里的state)只有两种状态:0表示未锁定,1表示锁定。下边是Mutex的核心源码:
class Mutex implements Lock, java.io.Serializable { // 自定义同步器 private static class Sync extends AbstractQueuedSynchronizer { // 判断是否锁定状态 protected boolean isHeldExclusively() { return getState() == 1; } // 尝试获取资源,立即返回。成功则返回true,否则false。 public boolean tryAcquire(int acquires) { assert acquires == 1; // 这里限定只能为1个量 if (compareAndSetState(0, 1)) {//state为0才设置为1,不可重入! setExclusiveOwnerThread(Thread.currentThread());//设置为当前线程独占资源 return true; } return false; } // 尝试释放资源,立即返回。成功则为true,否则false。 protected boolean tryRelease(int releases) { assert releases == 1; // 限定为1个量 if (getState() == 0)//既然来释放,那肯定就是已占有状态了。只是为了保险,多层判断! throw new IllegalMonitorStateException(); setExclusiveOwnerThread(null); setState(0);//释放资源,放弃占有状态 return true; } } // 真正同步类的实现都依赖继承于AQS的自定义同步器! private final Sync sync = new Sync(); //lock<-->acquire。两者语义一样:获取资源,即便等待,直到成功才返回。 public void lock() { sync.acquire(1); } //tryLock<-->tryAcquire。两者语义一样:尝试获取资源,要求立即返回。成功则为true,失败则为false。 public boolean tryLock() { return sync.tryAcquire(1); } //unlock<-->release。两者语文一样:释放资源。 public void unlock() { sync.release(1); } //锁是否占有状态 public boolean isLocked() { return sync.isHeldExclusively(); } }
同步类在实现时一般都将自定义同步器(sync)定义为内部类,供自己使用;而同步类自己(Mutex)则实现某个接口,对外服务。当然,接口的实现要直接依赖sync,它们在语义上也存在某种对应关系!!而sync只用实现资源state的获取-释放方式tryAcquire-tryRelelase,至于线程的排队、等待、唤醒等,上层的AQS都已经实现好了,我们不用关心。
除了Mutex,ReentrantLock/CountDownLatch/Semphore这些同步类的实现方式都差不多,不同的地方就在获取-释放资源的方式tryAcquire-tryRelelase。掌握了这点,AQS的核心便被攻破了!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~