阅读 51

ReentrantReadWriteLock有感

看完ReentrantLock后再来看看ReentrantReadWriteLock读写锁:

ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  线程1 readWriteLock.writeLock().lock();
  
  线程1来获取写锁
  protected final boolean tryAcquire(int acquires) {
            //当前线程1
            Thread current = Thread.currentThread();
            //state=0,c=0
            int c = getState();
            //c=0,w=0  int state是32位的二进制
            //读写锁把state的低16位作为写锁标志,高16位作为读锁标志
            //c=0,它的低16位也是0
            int w = exclusiveCount(c);
            if (c != 0) {
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                setState(c + acquires);
                return true;
            }
            //然后走到这,writerShouldBlock()=false,CAS将state=1,并将占有锁线程设为线程1
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }
  
  这样线程1成功获取来读锁
  
  线程2 readWriteLock.writeLock().lock();
  此时线程2来获取写锁了,c=1,w!=0,但是current != getExclusiveOwnerThread(),返回false加锁失败,然后就加入到队列阻塞等待了,与之前ReentrantLock类似
  if (w == 0 || current != getExclusiveOwnerThread())这个说明加了读锁,加了写锁就不能加读锁了
  
  线程3 readWriteLock.readLock().lock(); 此时线程3来获取读锁了
  public final void acquireShared(int arg) {
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    }
protected final int tryAcquireShared(int unused) {
            Thread current = Thread.currentThread();
            int c = getState();
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;
            int r = sharedCount(c);
            if (!readerShouldBlock() &&
                r < MAX_COUNT &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                if (r == 0) {
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    firstReaderHoldCount++;
                } else {
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                }
                return 1;
            }
            return fullTryAcquireShared(current);
        } 
此时c=state=1, 
exclusiveCount(c) != 0 &&getExclusiveOwnerThread() != current  为true,返回-1  ,可以看出加了写锁,就不能加读锁了 ,读锁与写锁互斥
然后就加入到队列,阻塞等待了,waitStatus=SHARED 表示读锁

假设现在线程1,释放了写锁,然后唤醒了线程2,线程2获取到了读锁
此时 线程3 readWriteLock.writeLock().lock(); 来获取读锁了
r = sharedCount(c); 是state的高16位,线程2已经获取了读锁,所以r!=0,

下面这段代码就是指获取读锁成功后,做的一些记录。像线程2就是firstReader
if (r == 0) {
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    firstReaderHoldCount++;
                } else {
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                }

复制代码
文章分类
阅读
文章标签