AQS源码阅读理解(uncompleted)
有head和tail当acquire*操作的时候,如果我们定义的资源限制操作返回false时,会在tail端加入一个新的节点(Node里面的所有基础属性都是volatile,用CAS设置tail指针)。然后利用LockSupport.part(this)阻塞。当release的时候,如果我们定义的资源操作返回true,会将head节点的下一个SIGNAL节点的thread唤醒。被唤醒的那个线程会继续尝试执行tryAcquire,这时候会和新线程的请求发生争用,ReentrantLock在这里做了两种策略,一种是判断当前线程是否在链表的第一个位置(fair),一种是不做判断直接争用(unfair)?shouldParkAfterFailedAcquire会判断当前加入的节点的前一个节点是否未获得锁(SIGNAL),如果未获得,就返回true,告诉后面该part当前thread了如果前个线程是CANCELLED的,删除CANCELLED节点,返回false。如果是0,设置为SIGNAL,返回false也就是说,它做的主要做的是清理的工作,如果是false,就不会去part当前thread,而是再继续走for循环。这样能保证每次醒来的节点会清理一遍前面的CANCELLED节点,让p==head可以通过?Interruptibly式的获取:其他线程对这个线程进行中断,导致LockSupport.part(this)继续执行,返回Thread.interrupted();外部会break-for,在for外层cancel该节点,并抛出InterruptedExceptionNanos式的获取:LockSupport.parkNanos(this, nanos),每次醒来都会检查时间,如果时间超出,cancel该节点???方法:独占获取: ? ? ? ? ? ?acquire ? ? ? ? ? ? ? ? ? ? acquireInterruptibly ? ? ? ? ? ? ? ? ? ?tryAcquireNanos?tryAcquire ? ? ? ? ? ? ?acquireQueued ? ? ? ? ?doAcquireInterruptibly ? ? ? ? ? ? ? ?doAcquireNanos共享获取: ? ? ? ? ? ?acquireShared ? ? ? ? ? acquireSharedInterruptibly ? ? ? ? ?tryAcquireSharedNanostryAcquireShared ? ?doAcquireShared ? ? ? doAcquireSharedInterruptibly ? ? ?doAcquireSharedNanos?独占释放: ? ? ? ? ? ? release ? ? ? ? ? ? ? ? ? ??tryRelease共享释放: ? ? ? ? ? ? releaseShared ? ? ? ? ??tryReleaseShared ? ?doReleaseShared?hasQueuedThreads ?hasContented ? ? getFirstQueuedThread ? ? isFirst ? ? fullIsFirst ? ? getQueuedLength ? ?getQueuedThreads ? ??getExeclusiveQueuedThreads ? ? getSharedQueuedThreads ? ? getWaitingThreadsowns ? ? hasWaiters ? ? getWaitQueueLength?shouldParkAfterFailedAcquireunparkSuccessorsetHeadAndPropagatecancelAcquire??Condition内部成员:firstWaiter、lastWaiter。内部包含一条Node链内部方法:signal、signalAllawait、awaitNanos、awaitUnit、await(long, TimeUnit)、awaitUninterruptiblyhasWaiters、getWaitQueueLength、getWaitingThreadsisOwnedBy(AQS)?执行await*操作时,会往末尾(lastWaiter)里添加nextWaiter然后释放资源(release(state)),调用LockSupport.park(this)执行signal操作时,会将firstWaiter移到sync queue末尾,调用的还是enq(node),并且将该node的waitStatus设置成SIGNAL,然后在程序执行lock.release时可以按正常资源释放的操作进行。?调用阻塞的入口两种,AQS.acquire和Condition.await