staticfinalclassNode{/** Marker to indicate a node is waiting in shared mode */// 标识节点当前在共享模式下staticfinalNodeSHARED=newNode();/** Marker to indicate a node is waiting in exclusive mode */// 标识节点当前在独占模式下staticfinalNodeEXCLUSIVE=null;// ======== 下面的几个int常量是给waitStatus用的 ===========/** waitStatus value to indicate thread has cancelled */// 表示此线程取消了争抢这个锁staticfinalintCANCELLED=1;/** waitStatus value to indicate successor's thread needs unparking *///被标识为该等待唤醒状态的后继结点,当其前继结点的线程释放了同步锁或被取消,//将会通知该后继结点的线程执行。//就是处于唤醒状态,只要前继结点释放锁,就会通知标识为SIGNAL状态的后继结点的线程执行。staticfinalintSIGNAL=-1;/** waitStatus value to indicate thread is waiting on condition *///该标识的结点处于等待队列中,结点的线程等待在Condition上,等待其他线程唤醒//当其他线程调用了Condition的signal()方法后,CONDITION状态的结点将//从等待队列转移到同步队列中,等待获取同步锁。staticfinalintCONDITION=-2;/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/// 与共享模式相关,在共享模式中,该状态标识结点的线程处于可运行状态。staticfinalintPROPAGATE=-3;// =====================================================// 节点的等待状态// 取值为上面的1、-1、-2、-3,或者0// 这么理解,暂时只需要知道如果这个值 大于0 代表此线程取消了等待,// 也许就是说半天抢不到锁,不抢了,ReentrantLock是可以指定timeouot的//AQS在判断状态时,通过用waitStatus>0表示取消状态,而waitStatus<0表示有效状态。volatileintwaitStatus;// 前驱节点的引用volatileNodeprev;// 后继节点的引用volatileNodenext;// 这个就是线程对象volatileThreadthread;}
/**
* Sync object for fair locks
*/staticfinalclassFairSyncextendsSync{privatestaticfinallongserialVersionUID=-3000897897090466540L;//争锁finalvoidlock(){//1acquire(1);}/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/protectedfinalbooleantryAcquire(intacquires){finalThreadcurrent=Thread.currentThread();intc=getState();if(c==0){if(!hasQueuedPredecessors()&&compareAndSetState(0,acquires)){setExclusiveOwnerThread(current);returntrue;}}elseif(current==getExclusiveOwnerThread()){intnextc=c+acquires;if(nextc<0)thrownewError("Maximum lock count exceeded");setState(nextc);returntrue;}returnfalse;}}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
* 尝试直接获取锁,返回值是boolean,代表是否获取到锁
* 返回true:1.没有线程在等待锁;2.重入锁,线程本来就持有锁,也就可以理所当然可以直接获取
*/protectedfinalbooleantryAcquire(intacquires){//获取当前线程finalThreadcurrent=Thread.currentThread();//查看锁的状态intc=getState();//state == 0 此时此刻没有线程持有锁 可以直接获取锁if(c==0){//由于是公平锁 则在获取锁之前先看一下队列中还有没有其他等待的线程//讲究先来后到 所以是公平锁 这也是和非公平锁的差别//非公平锁在这里会直接尝试获取锁//1.1.1if(!hasQueuedPredecessors()&&// 如果没有线程在等待,那就用CAS尝试获取一下锁// 不成功的话,只能说明几乎同一时刻有个线程抢先获取到了锁//因为刚才hasQueuedPredecessors判断是前面没有线程在等待的//1.1.2compareAndSetState(0,acquires)){//获取到锁后把当前线程设置为锁的拥有者//1.1.3setExclusiveOwnerThread(current);//获取锁成功直接返回truereturntrue;}}//到这里说明当前锁已经被占了//然后判断如果当前线程就是持有锁的线程//那么这次就是锁的重入elseif(current==getExclusiveOwnerThread()){//把state加1intnextc=c+acquires;if(nextc<0)thrownewError("Maximum lock count exceeded");//1.1.4setState(nextc);returntrue;}//上面两个条件都不满足就返回false//获取锁失败了 回到上一个方法继续看returnfalse;}
1.1.1 hasQueuedPredecessors()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 通过判断"当前线程"是不是在CLH队列的队首
* 来返回AQS中是不是有比“当前线程”等待更久的线程
*/publicfinalbooleanhasQueuedPredecessors(){// The correctness of this depends on head being initialized// before tail and on head.next being accurate if the current// thread is first in queue.Nodet=tail;// Read fields in reverse initialization orderNodeh=head;Nodes;returnh!=t&&((s=h.next)==null||s.thread!=Thread.currentThread());}
1.1.2 compareAndSetState(0, acquires))
1
2
3
4
5
6
7
/**
* 通过CAS设置锁的状态
*/protectedfinalbooleancompareAndSetState(intexpect,intupdate){// See below for intrinsics setup to support thisreturnunsafe.compareAndSwapInt(this,stateOffset,expect,update);}
/**
* 进入这里说明抢到锁,这个方法说的是:"当前线程没有抢到锁,是否需要挂起当前线程?"
* 第一个参数是前驱节点,第二个参数代表当前线程的节点 这里一共有三个规则
* 1.如果前继的节点状态为SIGNAL,表明当前节点需要unpark,则返回true 将导致线程阻塞
* 2.如果前继节点状态为CANCELLED(ws>0),说明前置节点已经被放弃,则找到一个非取消的前驱节点 * 返回false,acquireQueued方法的无限循环将递归调用该方法,直至规则1返回true
* 3.如果前继节点状态为非SIGNAL、非CANCELLED,则设置前继的状态为SIGNAL
* 返回false后进入acquireQueued的无限循环,与规则2同
*/privatestaticbooleanshouldParkAfterFailedAcquire(Nodepred,Nodenode){intws=pred.waitStatus;// 前驱节点的 waitStatus == -1 ,说明前驱节点状态正常,当前线程需要挂起,直接可以返回trueif(ws==Node.SIGNAL)/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/returntrue;// 前驱节点 waitStatus大于0 ,说明前驱节点取消了排队。// 进入阻塞队列排队的线程会被挂起,而唤醒的操作是由前驱节点完成的。// 所以下面这块代码说的是将当前节点的prev指向waitStatus<=0的节点,// 就是为当前节点找一个正常的前驱节点 毕竟当前节点需要等着前驱节点来唤醒if(ws>0){/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/// 这里就在循环直到找到一个waitStatus 不大于 0的前驱节点do{node.prev=pred=pred.prev;}while(pred.waitStatus>0);pred.next=node;}else{/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/// 仔细想想,如果进入到这个分支意味着什么// 前驱节点的waitStatus不等于-1也不大于0,那也就是只可能是0,-2,-3// 这里说明一下:每个新的node入队时,waitStatu都是0// 用CAS将前驱节点的waitStatus设置为Node.SIGNAL(也就是-1)compareAndSetWaitStatus(pred,ws,Node.SIGNAL);}returnfalse;}
/**
* Wakes up node's successor, if one exists.
* 唤醒后继节点 如果有的话
* @param node the node 参数node是head头结点
*/privatevoidunparkSuccessor(Nodenode){/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/intws=node.waitStatus;// 如果head节点当前waitStatus<0, 将其修改为0if(ws<0)compareAndSetWaitStatus(node,ws,0);/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/// 下面的代码就是唤醒后继节点,但是有可能后继节点取消了等待(waitStatus==1)Nodes=node.next;//如果直接后继节点是null或者 waitStatus > 0即取消了等待//那么就直接从队尾往前找,找到waitStatus<=0的所有节点中排在最前面的if(s==null||s.waitStatus>0){s=null;// 从后往前找,不必担心中间有节点取消(waitStatus==1)的情况for(Nodet=tail;t!=null&&t!=node;t=t.prev)if(t.waitStatus<=0)s=t;}//如果直接后继节点不是空的就直接唤醒if(s!=null)// 唤醒线程LockSupport.unpark(s.thread);}