当前位置: 首页 > 后端技术 > Java

JUC2AQS的整体框架

时间:2023-04-01 21:58:00 Java

AQS是Java提供的底层同步工具类。它使用一个volatileint状态变量来表示同步状态(表示共享资源),并提供一系列的CAS操作来管理这个同步状态。同时,它还维护了一个FIFO线程同步队列(双向队列,当多线程争用资源被阻塞时会进入这个队列,使用unsafe等待和唤醒线程)。AQS的主要作用是为Java中的并发同步组件提供统一的底层支持。比如常用的ReentrantLock、Semaphore、CountDownLatch等都是基于AQS实现的。用法是通过继承AQS实现其模板方法,然后将子类作为同步组件的内部类。状态访问方式一共有三种:getState()setState()compareAndSetState()AQS定义了两种资源共享方式:Exclusive(独占,只有一个线程可以执行,比如ReentrantLock)Share(共享,多个线程可以同时执行,如Semaphore/CountDownLatch)自定义同步器只需要实现共享资源状态的获取和释放即可。自定义同步器主要实现了以下几个方法:isHeldExclusively():线程是否独占资源。只有在使用条件时才需要执行它。tryAcquire(int):独占模式。尝试获取资源,成功时返回true,失败时返回false。tryRelease(int):独占模式。尝试释放资源,成功时返回true,失败时返回false。tryAcquireShared(int):共享方法。尝试获取资源。负数表示失败;0表示成功,但没有剩余资源;正数表示成功,剩余资源。tryReleaseShared(int):共享方法。尝试释放资源,如果释放后允许唤醒后续等待节点,则返回true,否则返回false。独占锁示例/***实现独占锁*/publicclassMuteximplementsLock{privatestaticclassSyncextendsAbstractQueuedSynchronizer{//是否独占protectedbooleanisHeldExclusively(){returngetState()==1;}//独占只有一个获取publicbooleantryAcquire(intacquires){if(compareAndSetState(0,1)){setExclusiveOwnerThread(Thread.currentThread());返回真;}返回假;}//释放锁保护booleantryRelease(intrelease){if(getState()==0){thrownewIllegalMonitorStateException();}setExclusiveOwnerThread(null);设置状态(0);返回真;}条件newCondition(){返回新的ConditionObject();}}privatefinalSyncsync=newSync();@Overridepublicvoidlock(){同步。获取(1);}@Override酒馆licvoidlockInterruptibly()throwsInterruptedException{同步。acquireInterruptibly(1);}@OverridepublicbooleantryLock(){返回同步。尝试获取(1);}@OverridepublicbooleantryLock(longtime,TimeUnitunit)throwsreynctException{.tryAcquireNanos(1,unit.toNanos(time));}@Overridepublicvoidunlock(){sync.release(1);}@OverridepublicConditionnewCondition(){returnsync.newCondition();}//是独占锁publicbooleanisLock(){returnsync.isHeldExclusively();}publicbooleanhasQueuedThreads(){returnsync.hasQueuedThreads();}}例子中,通过实现Lock接口,然后使用内部类继承AbstractQueuedSynchronizer实现独占锁共享锁示例/***共享锁示例*/publicclassSharedLockInstanceimplementsLock{privatefinalSyncsync=newSync(2);publicLockInstance()throwsIllegalAccessException{}//内部类继承AbstractQueuedSynchronizerprivatestaticfinalclassSyncextendsAbstractQueuedSynchronizer{Sync(intstate)throwsIllegalAccessException{if(state<=0){thrownewIllegalAccessException("countmustlargethan0");}设置状态(状态);}@OverridepublicinttryAcquireShared(intarg){for(;;){System.out.println("tryacquire...");intcurrent=getState();intnow=当前-参数;if(now<0||compareAndSetState(current,now)){现在返回;}}}@OverridepublicbooleantryReleaseShared(intarg){for(;;){System.out.println("尝试释放...");intcurrent=getState();intnow=当前+参数;如果(compareAndSetState(当前,现在)){返回真;}}}条件newCondition(){返回新的ConditionObject();}}@Overridepublicvoidlock(){sync.acquireShared(1);}@OverridepublicvoidlockInterruptibly()throwsInterruptedException{sync.acquireInterruptibly(1);}@OverridepublicbooleantryLock(){returnsync.tryAcquireShared(1)>=0;}@OverridepublicbooleantryLock(longtime,TimeUnitunit)throwsInterruptedException{returnsync.tryAcquireSharedNanos(1,unit.toNanos(time));}@Overridepublicvoidunlock(){sync.tryReleaseShared(1);}@OverridepublicConditionnewCondition(){returnsync.newCondition();}}无论是独占锁还是共享锁,都继承了AQS中的模板方法。这些模板方法大致分为三类:同步状态的独占获取和释放、同步状态的共享获取和释放以及查询同步队列一般来说,自定义同步器要么是独占的,要么是共享的,只需要实现其中一个tryAcquire-tryRelease和tryAcquireShared-tryReleaseShared。但是AQS也支持自定义同步器实现独占和共享两种方式,比如ReentrantReadWriteLock。参考文章:AQS详解Java并发沉淀再出发:理解Java中的AQS