AQS

什么是AQS

AQS,指的是AbstractQueuedSynchronizer,它提供了一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架,ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier等并发类均是基于AQS来实现的。

AQS使用方式和其中的设计模式

继承,模板方法设计模式

独占式锁代表:ReentrantLock

共享式锁代表:ReadLock

模板方法:

独占式获取

accquire

acquireInterruptibly

tryAcquireNanos

共享式获取

acquireShared

acquireSharedInterruptibly

tryAcquireSharedNanos

独占式释放锁

release

共享式释放锁

releaseShared

需要子类覆盖的流程方法

独占式获取  tryAcquire

独占式释放  tryRelease

共享式获取 tryAcquireShared

共享式释放  tryReleaseShared

这个同步器是否处于独占模式  isHeldExclusively

同步状态state:

getState:获取当前的同步状态

setState:设置当前同步状态

compareAndSetState 使用CAS设置状态,保证状态设置的原子性

 LockSupport

主要用于将一个线程设置为阻塞状态,或者唤醒线程

 

pack 阻塞

unpack 唤醒                                                                                                                                                                               

独占式流程

 

 自实现ReentrantLock

public class MyReentrantLock implements Lock {
    //state 表示获取到锁 state=1 获取到了锁,state=0,表示这个锁当前没有线程拿到
    private static class Sync extends AbstractQueuedSynchronizer {
        //是否处于独占模式
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        //尝试获取锁
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) {
                //设置当前线程为锁拥有者
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        //尝试释放该锁
        @Override
        protected boolean tryRelease(int arg) {
            if(getState() == 0){//当前状态为未持有锁状态,则直接抛错
                throw new UnsupportedOperationException();
            }
            //设置锁的持有者为null
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        private Condition newCondition(){
            return new ConditionObject();
        }
    }

    static Sync sync = new Sync();

    @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();
    }
}
public class AQSTest {
    static Lock lock = new MyReentrantLock();

    static class MyThread extends Thread {
        @Override
        public void run() {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + " start to do work");
                Thread.sleep(5);
                System.out.println(Thread.currentThread().getName() + " work done");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new MyThread().start();
        }
    }
}

运行结果:

Thread-0 start to do work
Thread-0 work done
Thread-4 start to do work
Thread-4 work done
Thread-2 start to do work
Thread-2 work done
Thread-1 start to do work
Thread-1 work done
Thread-3 start to do work
Thread-3 work done

根据结果显示,独占锁生效。

自实现Semaphore

原理:设置共享锁,设定同时最多可以有几个线程获取该锁

public class MySemaphore implements Lock {
    Sync sync = new Sync(3);

    static class Sync extends AbstractQueuedSynchronizer {
        //设置AbstractQueuedSynchronizer的state的个数,根据对state的数量的判断,来实现同时最多几个线程获取锁
        Sync(int count) {
            if (count < 0) {
                throw new IllegalArgumentException("count must large than zero.");
            }
            setState(count);
        }

        //共享锁子类需要重写的方法
        @Override
        protected int tryAcquireShared(int reduceCount) {
            for (;;) {
                int current = getState();
                int newCount = current - reduceCount;
                if (newCount < 0 || compareAndSetState(current, newCount)) {
                    return newCount;
                }
            }
        }

        //共享锁子类需要重写的方法
        @Override
        protected boolean tryReleaseShared(int returnCount) {
            for (;;) {
                int current = getState();
                int newCount = current + returnCount;
                if (compareAndSetState(current, newCount)) {
                    return true;
                }
            }
        }

        Condition newCondition() {
            return new ConditionObject();
        }

    }

    @Override
    public void lock() {
        sync.acquireShared(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquireShared(1) >= 0;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.releaseShared(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }
}

public class MySemaphoreTest {
    static MySemaphore semaphore = new MySemaphore();

    static class MyThread extends Thread {
        @Override
        public void run() {
            semaphore.lock();
            try {
                System.out.println(Thread.currentThread().getName() + ":" + System.currentTimeMillis());
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.unlock();
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new MyThread().start();
        }
    }
}

运行结果:

Thread-0:1590145302725
Thread-2:1590145302725
Thread-1:1590145302725
Thread-4:1590145304725
Thread-5:1590145304725
Thread-6:1590145304726
Thread-3:1590145306725
Thread-8:1590145306725
Thread-9:1590145306726
Thread-7:1590145308725

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AQS的acquireQueued方法是在tryAcquire执行失败后,用于将当前线程加入到等待队列,并在适当的时候阻塞线程。具体流程如下: 1. 首先,使用addWaiter方法将当前线程添加到等待队列中,该方法会创建一个节点并将其插入到等待队列的尾部。 2. 然后,调用shouldParkAfterFailedAcquire方法来判断是否应该阻塞当前线程。该方法会根据前驱节点的等待状态来决定是否需要阻塞当前线程。 - 如果前驱节点的等待状态为Node.SIGNAL,表示前驱节点释放锁之后会唤醒当前节点,此时应该阻塞当前线程。 - 如果前驱节点的等待状态大于0,表示前驱节点取消了等待,需要将当前节点的前驱节点设置为前驱节点的前驱节点,直到找到一个等待状态不大于0的节点为止。然后将当前节点插入到该节点之后。 - 如果前驱节点的等待状态既不是Node.SIGNAL,也不大于0,则使用compareAndSetWaitStatus方法将前驱节点的等待状态设置为Node.SIGNAL,表示当前节点需要被唤醒。 3. 最后,根据shouldParkAfterFailedAcquire方法的返回值来判断是否需要阻塞当前线程。如果shouldParkAfterFailedAcquire方法返回false,表示不需要阻塞当前线程,则acquireQueued方法会一直自旋直到成功获取锁为止。如果shouldParkAfterFailedAcquire方法返回true,表示需要阻塞当前线程,则调用LockSupport.park方法阻塞当前线程,直到被唤醒为止。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [AQS核心流程解析-acquire方法](https://blog.csdn.net/IToBeNo_1/article/details/123404852)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值