AQS的原理和使用

    科技2023-11-29  102

    什么是AQS

    全称AbstractQueuedSynchronizer

    AQS实现是基于CLH队列锁

    CLH同步队列是一个FIFO双向队列,这三张图是来解释状态改变的过程,关于CLH可以自行查询

    多个线程时,myPred指向上一个存储的线程,并且自循检查前一个线程是否释放锁,自循一定次数后进入阻塞状态

    上一个线程的locked等于false时,当前线程就可以获取到锁。

    AQS使用方式

    实现见下面锁可重入示例代码

    AQS的设计模式

    模版模式:具体实现交给子类去实现。自己要实现同步锁,重写模版方法就可以实现。

    AQS中的核心方法

    tryAcquire和tryRelease方法。 AQS主要通过核心成员变量state来判断是否获取到锁。

    了解ReentrantLock锁
    锁的公平与非公平 公平锁 非公平锁

    区别在于公平锁判断当前线程在队列中前面是否还有其他线程

    锁的可重入

    同一个加锁方法,递归调用依然可以拿到锁,不会出现卡死的情况。

    例子: static final Lock lock = new ReenterSelfLock(); public void reenter(int x) { lock.lock(); try { System.out.println(Thread.currentThread().getName()+":递归层级:"+x); int y = x - 1; if (y==0) return; else{ reenter(y); } } finally { lock.unlock(); } } public void test() { class Worker extends Thread { public void run() { System.out.println(Thread.currentThread().getName()); SleepTools.second(1); reenter(3); } } // 启动3个子线程 for (int i = 0; i < 3; i++) { Worker w = new Worker(); w.start(); } 如何实现可重入锁: /** *类说明:实现独占锁,可重入 */ public class ReenterSelfLock implements Lock { /* 静态内部类,自定义同步器*/ private static class Sync extends AbstractQueuedSynchronizer { /* 是否处于占用状态*/ protected boolean isHeldExclusively() { return getState() > 0; } /* 当状态为0的时候获取锁*/ public boolean tryAcquire(int acquires) { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; }else if(getExclusiveOwnerThread()==Thread.currentThread()){ setState(getState()+1); return true; } return false; } /* 释放锁,将状态设置为0*/ protected boolean tryRelease(int releases) { if(getExclusiveOwnerThread()!=Thread.currentThread()){ throw new IllegalMonitorStateException(); } if (getState() == 0) throw new IllegalMonitorStateException(); setState(getState()-1); if(getState()==0){ setExclusiveOwnerThread(null); } return true; } /* 返回一个Condition,每个condition都包含了一个condition队列*/ Condition newCondition() { return new ConditionObject(); } } /* 仅需要将操作代理到Sync上即可*/ private final Sync sync = new Sync(); public void lock() { System.out.println(Thread.currentThread().getName()+" ready get lock"); sync.acquire(1); System.out.println(Thread.currentThread().getName()+" already got lock"); } public boolean tryLock() { return sync.tryAcquire(1); } public void unlock() { System.out.println(Thread.currentThread().getName()+" ready release lock"); sync.release(1); System.out.println(Thread.currentThread().getName()+" already released lock"); } public Condition newCondition() { return sync.newCondition(); } public boolean isLocked() { return sync.isHeldExclusively(); } public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } }

    在AQS的tryAcquire和tryRelease方法中分别对state本身加减

    Processed: 0.016, SQL: 8