AQS之工作原理

前面一章LZ简单的介绍了下AbstractQueuedSynchronizer(AQS)以及AQS中提供的一些模板方法和作用,这一章LZ将用一个简单的实例来介绍下AQS中独占锁的工作原理。独占锁顾名思义就是在同一时刻只能有一个线程能获取到锁,而其它需要获取这把锁的线程将进入到同步队列中等待获取到了锁的线程释放这把锁,只有获取锁的线程释放了锁,同步队列中的线程才能获取锁。LZ可以描述的有些绕,画图来解释下这段话的意思:

AQS原理

这个图则清晰的说明了AQS中独占锁的的基本原理,下面LZ将用一段简单的代码来看看AQS中独占锁的工作原理。

1public class ExclusiveDemo implements Lock { 2 // 静态内部类,自定义同步器 3 private static class Sync extends AbstractQueuedSynchronizer{ 4 // 是否处于独占状态 5 @Override 6 protected boolean isHeldExclusively() { 7 return this.getState() == 1; 8 } 9 // 当状态为0时,获取锁 10 @Override 11 protected boolean tryAcquire(int arg) { 12 if(compareAndSetState(0,1)){ 13 setExclusiveOwnerThread(Thread.currentThread()); 14 return true; 15 } 16 return false; 17 } 18 // 释放锁,将状态设置为0 19 @Override 20 protected boolean tryRelease(int arg) { 21 if(getState() == 0) throw new IllegalMonitorStateException(); 22 setExclusiveOwnerThread(null); 23 setState(0); 24 return true; 25 } 26 // 返回一个Condition,没给Condition都包含了一个Condition队列 27 Condition newCondition() { 28 return new ConditionObject(); 29 } 30 } 31 private final Sync sync = new Sync(); 32 @Override 33 public void lock() { 34 sync.acquire(1); 35 } 36 @Override 37 public void lockInterruptibly() throws InterruptedException { 38 sync.acquireInterruptibly(1); 39 } 40 @Override 41 public boolean tryLock() { 42 return sync.tryAcquire(1); 43 } 44 @Override 45 public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { 46 return sync.tryAcquireSharedNanos(1,unit.toNanos(time)); 47 } 48 @Override 49 public void unlock() { 50 sync.release(0); 51 } 52 @Override 53 public Condition newCondition() { 54 return sync.newCondition(); 55 } 56}

上面示例中,独占所ExclusiveDemo是一个自定义的同步组件,它在同一时刻只允许一个线程占有锁。ExclusiveDemo定义了一个静态内部类,该内部类继承了同步器并实现了独占式获取和释放同步状态。在tryAcquire方法中,通过CAS方式设置同步器状态,如果设置成功,返回true,设置失败返回false。tryRelease(int arg)方法是将同步器状态设置为0。通过上面的示例,我么可以看到,当我们在使用ExclusiveDemo的时候,我们并没有直接和同步器打交道,而是通过调用ExclusiveDemo提供的方法。这一章LZ只是简单的介绍了下AQS是如何工作的,下一章LZ分析下AQS中CHL的工作原理。


关注下面公众号,回复 1024 领取最新大厂面试资料

点赞
收藏

评论区

加载中...

相关推荐

notifyAll唤醒线程的范围?

今天看到开源中国上有这样一个问答:假设我有两个对象锁,对象A锁有5个线程在等待,对象B锁有3个线程在等待,对象A锁中的线程执行完,这时调用notifyAll,是唤醒了对象AB两个锁的全部的等待线程还是只唤醒了A锁的5个线程?1.方法文档解释通过看该方法文档的解释,可以得出下面结论:notifyAll()中All的含义是所有的线程,而不是所有的锁,只能唤

java中的锁

记录一下公平锁,非公平锁,可重入锁(递归锁),读写锁,自旋锁的概念,以及一些和锁有关的java类。公平锁与非公平锁:公平锁就是在多线程环境下,每个线程在获取锁时,先查看这个锁维护的队列,如果队列为空或者自身就是等待队列的第一个,就占有锁。否则就加入到等待队列中,按照FIFO的顺序依次占有锁。非公平锁会一上来就试图占

面试百度和美团,竟然问我多线程安全问题,正好撞在我知识点上

解决多线程安全问题无非两个方法synchronized和lock具体原理以及如何获取锁AQS算法本篇文章主要讲了lock的原理就是AQS算法,还有个姊妹篇讲解synchronized的实现原理也是阿里经常问的,一定要看后面的文章,先说结论:非公平锁tryAcquire的流程是:检查state字段,若为0,表示锁未被占用,那么尝试占用,若不为0,检查

Java并发包小结

1、Lock  Lock功能对应关键字synchrozied功能,lock和unlock方法用于加锁和释放锁。等待锁的线程加入到等待链表中,同时阻塞线程,锁释放时,从等待链表中取出等待的线程执行,取等待的线程分公平与非公平两种方式,公平方式取第一个等待的线程,非公平方式当前正在获取锁的线程可能立刻执行,而不用加入到等待队列中,排队执行。2、Con

Python的锁

互斥锁锁通常被用来实现对共享资源的同步访问。为每一个共享资源创建一个Lock对象,lLock()创建一个锁,初始状态是未锁定当你需要访问该资源时,调用l.acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用l.release方法释放锁!(https:

Java中的队列同步器AQS

一、AQS概念  1、队列同步器是用来构建锁或者其他同步组件的基础框架,使用一个int型变量代表同步状态,通过内置的队列来完成线程的排队工作。  2、下面是JDK8文档中对于AQS的部分介绍  publicabstractclassAbstractQueuedSynchronizerextendsAbstract