/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/publicReentrantLock(){
sync =newReentrantLock.NonfairSync();}/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/publicReentrantLock(boolean fair){
sync = fair ?newReentrantLock.FairSync():newReentrantLock.NonfairSync();}
公平锁和非公平锁具体实现
锁获取
/**
* Sync object for fair locks
*/staticfinalclassFairSyncextendsSync{privatestaticfinallong serialVersionUID =-3000897897090466540L;finalvoidlock(){acquire(1);}/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/protectedfinalbooleantryAcquire(int acquires){finalThread current =Thread.currentThread();int c =getState();if(c ==0){// 公平锁:当互斥资源未被占用,需要先判断等待队列中是否有线程,若有,先唤醒等待队列中线程if(!hasQueuedPredecessors()&&compareAndSetState(0, acquires)){setExclusiveOwnerThread(current);returntrue;}}elseif(current ==getExclusiveOwnerThread()){// 支持重入:当互斥资源被占用时,判断持有线程是否当前线程,若为当前线程,重入次数 +1int nextc = c + acquires;if(nextc <0)thrownewError("Maximum lock count exceeded");setState(nextc);returntrue;}returnfalse;}}/* 判断等待队列中是否存在等待中的线程 */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.Node t = tail;// Read fields in reverse initialization orderNode h = head;Node s;// 判断是否存在先等待的线程 具体分析如下return h != t &&((s = h.next)==null|| s.thread !=Thread.currentThread());}
hasQueuedPredecessors() 图示展示
/**
* Sync object for non-fair locks
*/staticfinalclassNonfairSyncextendsSync{privatestaticfinallong serialVersionUID =7316153563782823691L;/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/finalvoidlock(){// 非公平锁多次 CAS 直接尝试竞争锁 尽可能避免阻塞带来的上下文切换if(compareAndSetState(0,1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}protectedfinalbooleantryAcquire(int acquires){returnnonfairTryAcquire(acquires);}}/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/finalbooleannonfairTryAcquire(int acquires){finalThread current =Thread.currentThread();int c =getState();if(c ==0){// 非公平锁:直接竞争锁,不管等待是否存在等待节点if(compareAndSetState(0, acquires)){setExclusiveOwnerThread(current);returntrue;}}elseif(current ==getExclusiveOwnerThread()){int nextc = c + acquires;if(nextc <0)// overflowthrownewError("Maximum lock count exceeded");setState(nextc);returntrue;}returnfalse;}
锁释放
protectedfinalbooleantryRelease(int releases){int c =getState()- releases;// 获取独占锁的线程才可以释放线程if(Thread.currentThread()!=getExclusiveOwnerThread())thrownewIllegalMonitorStateException();boolean free =false;// state == 0 表示所有锁已释放if(c ==0){
free =true;setExclusiveOwnerThread(null);}setState(c);return free;}
可重入
当互斥资源被占用时,判断持有线程是否当前线程,若为当前线程,重入次数 +1
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/protectedfinalbooleantryAcquire(int acquires){finalThread current =Thread.currentThread();int c =getState();if(c ==0){if(!hasQueuedPredecessors()&&compareAndSetState(0, acquires)){setExclusiveOwnerThread(current);returntrue;}}elseif(current ==getExclusiveOwnerThread()){// 支持重入:当互斥资源被占用时,判断持有线程是否当前线程,若为当前线程,重入次数 +1int nextc = c + acquires;if(nextc <0)thrownewError("Maximum lock count exceeded");setState(nextc);returntrue;}returnfalse;}
我们都知道 AQS 使用 state 字段记录锁的重入次数,而 ReentrantReadWriteLock 创意性的将 state 字段的高 16 位用于表示读状态,低 16 位表示写状态,把两个写操作合并到一个 CAS 操作。
ReadLock
获取锁
protectedfinalinttryAcquireShared(int unused){/*
* Walkthrough:
* 1. If write lock held by another thread, fail.
* 2. Otherwise, this thread is eligible for
* lock wrt state, so ask if it should block
* because of queue policy. If not, try
* to grant by CASing state and updating count.
* Note that step does not check for reentrant
* acquires, which is postponed to full version
* to avoid having to check hold count in
* the more typical non-reentrant case.
* 3. If step 2 fails either because thread
* apparently not eligible or CAS fails or count
* saturated, chain to version with full retry loop.
*/Thread current =Thread.currentThread();int c =getState();// 存在写锁且不是当前线程if(exclusiveCount(c)!=0&&getExclusiveOwnerThread()!= current)return-1;// 当前线程持有写锁或仅有读锁或无锁int r =sharedCount(c);// 根据公平锁和非公平锁重写 readerShouldBlock()if(!readerShouldBlock()&& r <MAX_COUNT&&compareAndSetState(c, c +SHARED_UNIT)){// 如果是第一次获取 初始化 firstReader、firstReaderHoldCount 不是第一次获取 对 readHolds 对应线程计数+1if(r ==0){// 第一次添加读锁
firstReader = current;
firstReaderHoldCount =1;}elseif(firstReader == current){// firstReader 为当前线程
firstReaderHoldCount++;}else{// 否则更新 readHolds 对应线程读锁计数HoldCounter rh = cachedHoldCounter;if(rh ==null|| rh.tid !=getThreadId(current)) cachedHoldCounter = rh = readHolds.get();elseif(rh.count ==0) readHolds.set(rh);
rh.count++;}return1;}// 自旋尝试获取读锁(只要满足获取读锁条件)returnfullTryAcquireShared(current);}finalintfullTryAcquireShared(Thread current){/*
* This code is in part redundant with that in
* tryAcquireShared but is simpler overall by not
* complicating tryAcquireShared with interactions between
* retries and lazily reading hold counts.
*/HoldCounter rh =null;// 自旋 不挂起线程for(;;){int c =getState();if(exclusiveCount(c)!=0){// 非当前线程获取到写锁 获取失败if(getExclusiveOwnerThread()!= current)return-1;// else we hold the exclusive lock; blocking here// would cause deadlock.}elseif(readerShouldBlock()){// 走到这里说明没有写锁被占有 判断是否存在重入// Make sure we're not acquiring read lock reentrantly// 当前线程为 firstReader 走下面 CASif(firstReader == current){// assert firstReaderHoldCount > 0;}else{if(rh ==null){
rh = cachedHoldCounter;// cachedHoldCounter 没有缓存或缓存的不是当前线程if(rh ==null|| rh.tid !=getThreadId(current)){
rh = readHolds.get();// 说明上一行是初始化 移除上面产生的初始化if(rh.count ==0)
readHolds.remove();}}if(rh.count ==0)return-1;}}// 是否已经达到读锁获取次数上限if(sharedCount(c)==MAX_COUNT)thrownewError("Maximum lock count exceeded");// CAS 获取锁if(compareAndSetState(c, c +SHARED_UNIT)){// 读锁初始化和计数if(sharedCount(c)==0){// 第一次添加读锁
firstReader = current;
firstReaderHoldCount =1;}elseif(firstReader == current){// firstReader 为当前线程
firstReaderHoldCount++;}else{// 否则更新 readHolds 对应线程读锁计数if(rh ==null)
rh = cachedHoldCounter;if(rh ==null|| rh.tid !=getThreadId(current))
rh = readHolds.get();elseif(rh.count ==0)
readHolds.set(rh);
rh.count++;
cachedHoldCounter = rh;// cache for release}return1;}}}
释放锁
protectedfinalbooleantryReleaseShared(int unused){Thread current =Thread.currentThread();// 根据共享锁次数来设置 firstReader 不存在并发修改问题if(firstReader == current){// assert firstReaderHoldCount > 0;if(firstReaderHoldCount ==1)
firstReader =null;else
firstReaderHoldCount--;}else{Sync.HoldCounter rh = cachedHoldCounter;if(rh ==null|| rh.tid !=getThreadId(current))
rh = readHolds.get();int count = rh.count;if(count <=1){
readHolds.remove();if(count <=0)throwunmatchedUnlockException();}--rh.count;}// CAS 更新 statefor(;;){int c =getState();int nextc = c -SHARED_UNIT;if(compareAndSetState(c, nextc))// Releasing the read lock has no effect on readers,// but it may allow waiting writers to proceed if// both read and write locks are now free.return nextc ==0;}}
WriteLock
获取锁
protectedfinalbooleantryAcquire(int acquires){/*
* Walkthrough:
* 1. If read count nonzero or write count nonzero
* and owner is a different thread, fail.
* 2. If count would saturate, fail. (This can only
* happen if count is already nonzero.)
* 3. Otherwise, this thread is eligible for lock if
* it is either a reentrant acquire or
* queue policy allows it. If so, update state
* and set owner.
*/Thread current =Thread.currentThread();int c =getState();int w =exclusiveCount(c);// 存在读锁或写锁if(c !=0){// (Note: if c != 0 and w == 0 then shared count != 0)// 存在读锁或存在写锁但不是当前线程持有获取失败if(w ==0|| current !=getExclusiveOwnerThread())returnfalse;// 获取锁是否超过上限if(w +exclusiveCount(acquires)>MAX_COUNT)thrownewError("Maximum lock count exceeded");// Reentrant acquire// 走到这里说明当前线程持有写锁 重入setState(c + acquires);returntrue;}// 不存在锁 判断公平非公平阻塞策略 || 进行 CAS 尝试获取锁if(writerShouldBlock()||!compareAndSetState(c, c + acquires))returnfalse;setExclusiveOwnerThread(current);returntrue;}