AQS原理

49 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情

1 概述

AQS 是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架

特点:

  • 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取 锁和释放锁
    • getState - 获取 state 状态
    • setState - 设置 state 状态
    • compareAndSetState - cas 机制设置 state 状态
    • 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源
  • 提供了基于 FIFO 的等待队列,类似于 Monitor 的 EntryList
  • 条件变量来实现等待、唤醒机制,支持多个条件变量,类似于 Monitor 的 WaitSet

子类主要实现一些常见方法如:

  • tryAcquire
  • tryRelease
  • tryAcquireShared
  • tryReleaseShared
  • isHeldExclusively

默认抛出 UnsupportedOperationException

获取锁的案例

// 如果获取锁失败
if (!tryAcquire(arg)) {
 // 入队, 可以选择阻塞当前线程 park unpark
}

释放锁的案例

// 如果释放锁成功
if (tryRelease(arg)) {
 // 让阻塞线程恢复运行
}

2 自定义不可重入锁

自定义同步器

final class MySync extends AbstractQueuedSynchronizer {
    
     @Override
     protected boolean tryAcquire(int acquires) {
         if (acquires == 1){
             if (compareAndSetState(0, 1)) {
                 setExclusiveOwnerThread(Thread.currentThread());
                 return true;
             }
         }
         return false;
     }
     @Override
     protected boolean tryRelease(int acquires) {
         if(acquires == 1) {
             if(getState() == 0) {
                 throw new IllegalMonitorStateException();
             }
             setExclusiveOwnerThread(null);
             setState(0);
             return true;
         }
         return false;
     }
     protected Condition newCondition() {
         return new ConditionObject();
     }
     @Override
     protected boolean isHeldExclusively() {
         return getState() == 1;
     }
}

自定义锁

class MyLock implements Lock {
     static MySync sync = new MySync();
    
     @Override
     // 尝试,不成功,进入等待队列
     public void lock() {
         sync.acquire(1);
     }
    
     @Override
     // 尝试,不成功,进入等待队列,可打断
     public void lockInterruptibly() throws InterruptedException {
         sync.acquireInterruptibly(1);
     }
    
     @Override
     // 尝试一次,不成功返回,不进入队列
     public boolean tryLock() {
         return sync.tryAcquire(1);
     }
    
     @Override
     // 尝试,不成功,进入等待队列,有时限
     public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
         return sync.tryAcquireNanos(1, unit.toNanos(time));
     }
    
     @Override
     // 释放锁
     public void unlock() {
         sync.release(1);
     }
    
     @Override
     // 生成条件变量
     public Condition newCondition() {
         return sync.newCondition();
     }
}

测试

MyLock lock = new MyLock();
new Thread(() -> {
     lock.lock();
     try {
         log.debug("locking...");
         sleep(1);
     } finally {
         log.debug("unlocking...");
         lock.unlock();
     }
},"t1").start();

new Thread(() -> {
     lock.lock();
     try {
         log.debug("locking...");
     } finally {
         log.debug("unlocking...");
         lock.unlock();
     }
},"t2").start();

运行结果:

c.TestAqs [t1] - locking... 
c.TestAqs [t1] - unlocking... 
c.TestAqs [t2] - locking... 
c.TestAqs [t2] - unlocking...

不可重入测试

MyLock lock = new MyLock();
new Thread(() -> {
    lock.lock();
    log.debug("locking...");
    lock.lock();
    log.debug("locking...");
     try {
         log.debug("locking...");
         sleep(1);
     } finally {
         log.debug("unlocking...");
         lock.unlock();
     }
},"t1").start();

运行结果:

c.TestAqs [t1] - locking... 

该线程陷入死锁, 说明lock锁为不可重入锁.