JAVA并发之Lock(下——实现)

本文深入解析了ReentrantLock和ReentrantReadWriteLock的实现原理,包括公平锁与非公平锁的区别,以及读写锁的内部机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上一节中,描述了Lock包的核心基础–AQS,本节将讲述其具体实现:ReentrantLock,ReentrantReadWriteLock。在这之前先说一下必要定义。
可重入锁:已在syn章节提及过,此处详细描述。某个线程获取到锁之后,在未释放锁之前的时间内,当需要获取锁时不需要获取锁的操作,可直接拿到资源。
公平锁:通俗的说,就是先等待的线程先获得锁。
非公平锁:与公平锁相反,每次需要获取锁时大家一起竞争,并不是先到先得。锁。

一、ReentrantLock

ReentrantLock是可重入锁,独占锁,实现Lock接口,内部实现了公平锁与非公平锁两种锁形式,默认使用非公平锁。

一、属性


 private final Sync sync;

该类有属性Sync,用final修饰即初始化之后不可更改,Sync是AQS的一个子类,有两个子类NonfairSync与FairSync,分别用于实现非公平锁与公平锁。

二、静态内部类
接下来是静态内部类,这里使用静态内部类便是为了让这些类中的方法都只让ReentrantLock使用。


1.Sync
该类是AQS的子类,重写了一些方法(AQS需要实现,公平锁与非公平锁通用),是NonfairSync与FairSync的父类。
接下如acquire(),tryAcquire(),release()等属于AQS类的重要方法,在上一篇描述AQS的blog中已经详细阐述,此处不再阐述。

 abstract static class Sync extends AbstractQueuedSynchronizer {
        abstract void lock();
        //不公平获取锁
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            } else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
        //尝试释放锁
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }
        //是否拥有当前锁
        protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }
        //获取一个条件队列
        final ConditionObject newCondition() {
            return new ConditionObject();
        }
         //获取占有锁的线程
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }
         //获取该线程占有多少资源
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }
        //资源是否被抢占
        final boolean isLocked() {
            return getState() != 0;
        }
    }

上述代码实现都比较简单,根据注释就能了解,不再分析。
2.NonfairSync
该类是Sync的实现类,是不公平锁的实现。在ReentrantLock中使用的

static final class NonfairSync extends Sync {
    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
}

上述代码有两方法:
lock():获取独占锁,若未获取则将线程阻塞等待。实现较简单:使用CAS将state从0置为1,若成功则代表获取资源成功;若失败则调用acquire()进行操作。
tryAcquire():获取锁,此处是直接调用父类Sync的nonfairTryAcquire方法。
疑问:nonfairTryAcquire()方法是不公平的获取锁,为什么要置于父类中,而不是子类NonfairSync中?
解答:通过跟踪源码,发现nonfairTryAcquire方法除了此处还有一处调用,在ReentrantLock对外提供的tryLock()方法中,用于立刻获取独占锁。故若将该方法放入子类NonfairSync中,则公平锁无法提供此功能。而对于我们来说,即使我们实现的是公平锁,在某些时刻也需要此功能。
3.FairSync
该类是Sync的实现类,是公平锁的实现。在ReentrantLock中使用的

static final class FairSync extends Sync {
    final void lock() {
        acquire(1);
    }
    protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(current);
                return true;
            }
       }else if (current == getExclusiveOwnerThread()) {
           int nextc = c + acquires;
           if (nextc < 0)
              throw new Error("Maximum lock count exceeded");
           setState(nextc);
           return true;
        }
        return false;
    }
}

上述代码有两方法:
lock():获取独占锁,直接调用acquire()进行操作。
tryAcquire():获取锁。

4.总结
通过上述公平锁与非公平锁的实现,其区别在于:

  1. lock():获取独占锁,公平锁时直接调用acquire(1),将该线程放入队尾,等待获取;而非公平锁则是先直接获取锁(无论CLH队列中是否有其他线程在等待),失败才会将该线程放入队尾。
  2. tryAcquire():尝试获取锁,其实此方法只是获取锁过程中的一部分。其区别在于可以获取锁时,公平锁的处理是!hasQueuedPredecessors() &&compareAndSetState(0, acquires),需要在队列前面没有其他等待线程才会尝试获取锁;而非公平锁的处理是compareAndSetState(0, acquires),无论是否有其他线程,直接尝试获取锁。

三、构造器
ReentrantLock对外提供两个构造器:

public ReentrantLock() {
    sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}
  1. ReentrantLock(),默认构造器,默认使用非公平锁,故上文中描述该类默认使用非公平锁
  2. ReentrantLock(boolean fair),带参构造器,传入true则是公平锁,false是非公平锁

四、对外提供方法
ReentrantLock提供了一系列方法,都是基于AQS以及上述Sync系列静态内部类实现,实现原理较简单,作用见注释,不一一详述。

//获取锁,若未获取则将线程阻塞等待
public void lock() {
    sync.lock();
}
//获取锁。若未获取则将线程阻塞等待,直到获取锁。如果有中断请求就会产生中断异常
public void lockInterruptibly() throws InterruptedException {
    sync.acquireInterruptibly(1);
}
//立刻尝试获取锁
public boolean tryLock() {
    return sync.nonfairTryAcquire(1);
}
//立刻尝试在指定时间内获取锁,直接调用AQS中方法
public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {
    return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
//释放锁
public void unlock() {
    sync.release(1);
}
//获取新的等待队列
public Condition newCondition() {
    return sync.newCondition();
}
//获取当先线程占有资源数
public int getHoldCount() {
    return sync.getHoldCount();
}
//是否是当前线程占有锁
public boolean isHeldByCurrentThread() {
    return sync.isHeldExclusively();
}
//锁是否被持有
public boolean isLocked() {
    return sync.isLocked();
}
//是否是公平锁
public final boolean isFair() {
    return sync instanceof FairSync;
}
//获取持有锁的线程
protected Thread getOwner() {
    return sync.getOwner();
}
//是否有线程等待获取锁
 public final boolean hasQueuedThreads() {
    return sync.hasQueuedThreads();
}
//CLH队列长度
public final int getQueueLength() {
    return sync.getQueueLength();
}
//获取所有正在等待获取锁的线程,返回是list<Thread>
protected Collection<Thread> getQueuedThreads() {
    return sync.getQueuedThreads();
}
//等待队列中是否有等待线程
public boolean hasWaiters(Condition condition) {
    if (condition == null)
        throw new NullPointerException();
    if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
        throw new IllegalArgumentException("not owner");
    return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
//等待队列中的线程数
public int getWaitQueueLength(Condition condition) {
    if (condition == null)
        throw new NullPointerException();
    if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
        throw new IllegalArgumentException("not owner");
    return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
//获取所有等待队列中的线程,返回是list<Thread>
protected Collection<Thread> getWaitingThreads(Condition condition) {
    if (condition == null)
        throw new NullPointerException();
    if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
        throw new IllegalArgumentException("not owner");
    return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}

一、ReentrantReadWriteLock

ReentrantReadWriteLock是可重入锁。里面有两把锁,读锁与写锁,其中读锁采用共享锁,写锁采用独占锁。不能同时存在读锁与写锁。内部实现了公平锁与非公平锁两种锁形式,默认使用非公平锁。
写线程虽然一次只有一个访问数据,但读线程可以同时读取,而在实际中,读取往往都是大量的,写入是偶尔的,读-写锁利用了这一点。从理论上讲,与互斥锁相比,使用读-写锁所允许的并发性增强将带来更大的性能提高。在实践中,只有在多处理器上并且只在访问模式适用于共享数据时,才能完全实现并发性增强。
读写锁不能同时存在。

一、属性


private final ReentrantReadWriteLock.ReadLock readerLock;
private final ReentrantReadWriteLock.WriteLock writerLock;
final Sync sync;

该类有属性Sync,readerLock,writerLock,均用final修饰即初始化之后不可更改,Sync是AQS的一个子类,有两个子类NonfairSync与FairSync,分别用于实现非公平锁与公平锁。readerLock为读锁,writerLock为写锁

二、静态内部类
接下来是静态内部类,这里使用静态内部类便是为了让这些类中的方法都只让ReentrantLock使用。


1.Sync
该类是AQS的子类,重写了一些方法(AQS需要实现,公平锁与非公平锁通用),是NonfairSync与FairSync的父类。
接下如acquire(),tryAcquire(),release()等属于AQS类的重要方法,在上一篇描述AQS的blog中已经详细阐述,此处不再阐述。

    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 6317671515068378041L;

        /*
         * 锁状态state是int型,读写分为两部分,各用一个无符号short来表示
         * 低位的表示写锁即独享锁,高位的表示读锁共享数
         */
        // 这个16是两个字节,一个short的长度
        static final int SHARED_SHIFT   = 16;
        // 1左移16位,为00000000 00000001 00000000 00000000
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
        // 1左移16位,减1,为65535,读写的获取锁的最大次数
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

        // 右移16位,获取c高位的16位,表示读锁的共享总数(高位2字节全0)
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
        // 和两个字节的全1字节与操作,高位2字节全0,获取写锁的总数
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

        // 每个线程的计数器,保存读锁共享数
        static final class HoldCounter {
            int count = 0;
            final long tid = getThreadId(Thread.currentThread());
        }

        // ThreadLocal的子类
        static final class ThreadLocalHoldCounter
            extends ThreadLocal<HoldCounter> {
            // 初始化方法,返回HoldCounter
            public HoldCounter initialValue() {
                return new HoldCounter();
            }
        }

        // 读线程的一个集合,但不包括最后一个读线程和第一个读线程
        private transient ThreadLocalHoldCounter readHolds;
        // 最后一个读线程的计数
        private transient HoldCounter cachedHoldCounter;
        // 第一个读线程
        private transient Thread firstReader = null;
        // 第一个读线程的计数
        private transient int firstReaderHoldCount;

        Sync() {
            readHolds = new ThreadLocalHoldCounter();
            setState(getState()); // ensures visibility of readHolds
        }
        // 读锁的阻塞
        abstract boolean readerShouldBlock();

        // 写锁的阻塞
        abstract boolean writerShouldBlock();

        // 释放写锁
        protected final boolean tryRelease(int releases) {
            if (!isHeldExclusively())
                // 当前线程不是owner线程,不能进行释放
                throw new IllegalMonitorStateException();
            // 计算释放后的状态值    
            int nextc = getState() - releases;
            // 如果当前写锁释放后,看是否还有写锁,没有写锁返回true
            boolean free = exclusiveCount(nextc) == 0;
            if (free)
                // 没有写锁了将锁对象的当前owner置为null
                setExclusiveOwnerThread(null);
            // 更新state的新值
            setState(nextc);
            return free;
        }

        // 尝试获取写锁
        protected final boolean tryAcquire(int acquires) {
            // 当前线程
            Thread current = Thread.currentThread();
            // 状态c,包含读锁和写锁的总数
            int c = getState();
            // w表示写锁的总数
            int w = exclusiveCount(c);
            if (c != 0) {
                // 如果写锁为0,说明当前有读锁(也可能是当前线程有读锁),不能获取写锁
                // 如果写锁不为0,但是当前线程不是owner线程不可重入,不能获取写锁
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                // 写锁数量超过了65535报错
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // 这里已经说明写锁是当前线程可重入的了,直接设置state值,返回true
                setState(c + acquires);
                return true;
            }
            // c==0时,如果写需要阻塞或者设置状态失败,返回false
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            // 设置锁的owner独占标识
            setExclusiveOwnerThread(current);
            return true;
        }

        // 尝试释放读锁
        protected final boolean tryReleaseShared(int unused) {
            // 当前线程current
            Thread current = Thread.currentThread();
            // 如果当前线程是第一个获取读锁的
            if (firstReader == current) {
                // 当前线程读锁总数为1,直接将firstReader置为null
                if (firstReaderHoldCount == 1)
                    firstReader = null;
                // 如果不为1,那么减掉1即可
                else
                    firstReaderHoldCount--;
            } else {
                // 最后一个获取读锁的线程
                HoldCounter rh = cachedHoldCounter;
                // 如果当前线程也不是最后一个获取读锁的线程,从ThreadLocal中取
                if (rh == null || rh.tid != getThreadId(current))
                    rh = readHolds.get();
                // 当前线程读锁的个数
                int count = rh.count;
                // 如果count==1,释放了就为0,直接在ThreadLocal中去掉当前线程
                if (count <= 1) {
                    readHolds.remove();
                    // count<=0,此时抛出不匹配释放锁的异常
                    if (count <= 0)
                        throw unmatchedUnlockException();
                }
                // 正常情况下,将当前线程的读锁count值减1即可。
                --rh.count;
            }
            for (;;) {
                int c = getState();
                // 高位减1,新的读写锁值
                int nextc = c - SHARED_UNIT;
                // 尝试设置state值,预测之前为c,更新为nextc
                if (compareAndSetState(c, nextc))
                    // 释放读锁不会影响其他读锁,但是如果这时读写锁都空闲,等待中的写线程将开始执行
                    // 这里只有读写锁都释放了,才返回true
                    return nextc == 0;
            }
        }

        // 释放读锁的不匹配异常
        private IllegalMonitorStateException unmatchedUnlockException() {
            return new IllegalMonitorStateException(
                "attempt to unlock read lock, not locked by current thread");
        }

        // 尝试获取读锁
        protected final int tryAcquireShared(int unused) {
            // 当前线程
            Thread current = Thread.currentThread();
            // 锁的state值
            int c = getState();
            // 如果有独占标识同时当前线程并不是独占线程时,直接返回-1
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;
            // 读锁的总数
            int r = sharedCount(c);
            // 如果读不需要阻塞,同时读锁小于65535,并且能够CAS设置c的值读个数加1
            // 这里的阻塞策略readerShouldBlock进行了判断,有两种情况:
            // 1.公平模式:如果AQS队列前面有等待的结点,当前线程应该阻塞
            // 2.非公平模式:如果AQS前面有线程在等待写锁,当前线程应该阻塞(这样做的原因是为了防止写饥饿)。
            // 出现这个阻塞情况,就不走下边的if了,直接到最后走fullTryAcquireShared方法处理
            if (!readerShouldBlock() &&
                r < MAX_COUNT &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                // 读锁个数为0,将当前线程作为第一个读线程单独保存,不存在ThreadLocal中
                if (r == 0) {
                    firstReader = current;
                    // 当前线程即第一个读线程的读锁总数置为1
                    firstReaderHoldCount = 1;
                // 如果r!=0,说明有读线程了,判断当前线程是不是第一个读线程
                } else if (firstReader == current) {
                    // 如果当前线程就是第一个读线程,数量count加1即可
                    firstReaderHoldCount++;
                } else {
                    // 当前线程不是第一个读线程,判断是不是最后一个读线程
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        // 当前线程不是最后一个读线程,从ThreadLocal中取线程
                        // 同时将最后一个读线程更新为当前线程
                        cachedHoldCounter = rh = readHolds.get();
                    // 这里如果当前线程就是最后一个读线程的话,如果count为0
                    else if (rh.count == 0)
                        // 需要重新set当前线程(之前释放时,readHolds.remove()进行过这个操作)
                        readHolds.set(rh);
                    // 将当前线程的count加1
                    rh.count++;
                }
                // 返回值1说明获取读锁成功了
                return 1;
            }
            // 读线程阻塞时,执行这个方法
            return fullTryAcquireShared(current);
        }

        // 该方法处理读线程阻塞的情况
        final int fullTryAcquireShared(Thread current) {
            HoldCounter rh = null;
            for (;;) {
                int c = getState();
                // 独占标记存在且当前owner不是当前线程,不能重入
                if (exclusiveCount(c) != 0) {
                    if (getExclusiveOwnerThread() != current)
                        return -1;
                // 没有写锁存在时,如果读阻塞
                // 这里的阻塞策略,如果:1.公平模式:如果当前AQS队列前面有等待的结点,返回false;2.非公平模式:如果
// AQS前面有线程在等待写锁,返回false(这样做的原因是为了防止写饥饿)。
                } else if (readerShouldBlock()) {
                    // 如果当前线程是第一个读线程
                    if (firstReader == current) {

                    } else {
                        if (rh == null) {
                            // 优先赋值成上一次获取读锁成功的cache,即最后一个读锁
                            rh = cachedHoldCounter;
                            if (rh == null || rh.tid != getThreadId(current)) {
                                // 如果和当前线程不匹配,从ThreadLocal中取
                                rh = readHolds.get();
                                if (rh.count == 0)
                                    readHolds.remove();
                            }
                        }
                        // 不是读锁重入的情况,返回-1
                        if (rh.count == 0)
                            return -1;
                    }
                }
                // 如果读锁总数为65535,报错
                if (sharedCount(c) == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // 如果CAS将c的读锁总数增加1成功
                if (compareAndSetState(c, c + SHARED_UNIT)) {
                    // 如果读锁数量为0,当前线程作为第一个线程存起来
                    if (sharedCount(c) == 0) {
                        firstReader = current;
                        firstReaderHoldCount = 1;
                    // 当前线程为第一个获取读锁的线程,数量加1
                    } else if (firstReader == current) {
                        firstReaderHoldCount++;
                    // 其他情况,和之前的方法同样原理
                    } else {
                        if (rh == null)
                            rh = cachedHoldCounter;
                        if (rh == null || rh.tid != getThreadId(current))
                            rh = readHolds.get();
                        else if (rh.count == 0)
                            readHolds.set(rh);
                        rh.count++;
                        cachedHoldCounter = rh; // cache for release
                    }
                    return 1;
                }
            }
        }

        // 和tryAcquire基本一致,去掉了考虑阻塞部分,相当于非公平模式的获取写锁
        final boolean tryWriteLock() {
            Thread current = Thread.currentThread();
            int c = getState();
            if (c != 0) {
                int w = exclusiveCount(c);
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                if (w == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
            }
            if (!compareAndSetState(c, c + 1))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }

        // 和tryAcquireShared函数基本一致,去掉了考虑阻塞部分,相当于非公平模式的获取读锁
        final boolean tryReadLock() {
            Thread current = Thread.currentThread();
            for (;;) {
                int c = getState();
                if (exclusiveCount(c) != 0 &&
                    getExclusiveOwnerThread() != current)
                    return false;
                int r = sharedCount(c);
                if (r == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                if (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 true;
                }
            }
        }

        protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        final Thread getOwner() {
            return ((exclusiveCount(getState()) == 0) ?
                    null :
                    getExclusiveOwnerThread());
        }

        final int getReadLockCount() {
            return sharedCount(getState());
        }

        final boolean isWriteLocked() {
            return exclusiveCount(getState()) != 0;
        }

        final int getWriteHoldCount() {
            return isHeldExclusively() ? exclusiveCount(getState()) : 0;
        }

        final int getReadHoldCount() {
            if (getReadLockCount() == 0)
                return 0;

            Thread current = Thread.currentThread();
            if (firstReader == current)
                return firstReaderHoldCount;

            HoldCounter rh = cachedHoldCounter;
            if (rh != null && rh.tid == getThreadId(current))
                return rh.count;

            int count = readHolds.get().count;
            if (count == 0) readHolds.remove();
            return count;
        }

        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            readHolds = new ThreadLocalHoldCounter();
            setState(0); // reset to unlocked state
        }

        final int getCount() { return getState(); }
    }

此静态内部类是ReentrantReadWriteLock的关键所在,过程已经在注释中详细描述,在此说明设计核心思想:

如何表示多个读锁与单个写锁 :由于state字段是32位的int,在次将state一分为2,用高16位记录读锁(共享锁)的状态,低16位保存写锁(独占锁)的状态,因此锁的数量上限都是65535
如何表示每个读锁、写锁的重入次数:可以把线程重入读锁的次数作为值存在 ThreadLocal 中

2.NonfairSync与FairSync

    static final class NonfairSync extends Sync {
        final boolean writerShouldBlock() {
            return false; // writers can always barge
        }
        final boolean readerShouldBlock() {
            return apparentlyFirstQueuedIsExclusive();
        }
    }
    static final class FairSync extends Sync {
        final boolean writerShouldBlock() {
            return hasQueuedPredecessors();
        }
        final boolean readerShouldBlock() {
            return hasQueuedPredecessors();
        }
    }

此处将公平锁与非公平锁放在一处,因为大多数逻辑已经在它们的父类Sync中实现,此处各只有两个方法:

  1. writerShouldBlock :写锁是阻塞进入等待队列(true)还是直接获取锁(false)。在非公平锁中,直接返回false;公平锁中,若无等待线程则返回false,有等待线程返回true
  2. readerShouldBlock:读锁是阻塞进入等待队列(true)还是直接获取锁(false)。在非公平锁中,如果队列的head.next正在等待独占锁(写锁),则返回true,否则返回false;公平锁中,若无等待线程则返回false,有等待线程返回true

3.ReadLock

public static class ReadLock implements Lock, java.io.Serializable {
        private final Sync sync;

        protected ReadLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        public void lock() {
            sync.acquireShared(1);
        }

        public void lockInterruptibly() throws InterruptedException {
            sync.acquireSharedInterruptibly(1);
        }

        public boolean tryLock() {
            return sync.tryReadLock();
        }

        public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
        }

        public void unlock() {
            sync.releaseShared(1);
        }

        public Condition newCondition() {
            throw new UnsupportedOperationException();
        }

    }

内部有一属性为sync,是从外部类继承过来,使用同一syn。使用共享锁,至于方法与ReentrantLock类似,同名方法作用一样,实现都是调用AQS以及Syn及子类方法,再次不赘述。
唯一需要注意的是,condition队列只支持独占锁,故此处不支持condition相关操作,直接抛出异常。
4.WriteLock

public static class WriteLock implements Lock, java.io.Serializable {
        private final Sync sync;
        protected WriteLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }
        //获取锁。若未获取则将线程阻塞等待
        public void lock() {
            sync.acquire(1);
        }
        //获取锁。若未获取则将线程阻塞等待,直到获取锁。如果有中断请求就会产生中断异常
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
        //尝试立刻获取锁
        public boolean tryLock( ) {
            return sync.tryWriteLock();
        }
        //尝试立刻在指定时间内获取锁
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }
        //释放锁
        public void unlock() {
            sync.release(1);
        }
        //获取等待队列
        public Condition newCondition() {
            return sync.newCondition();
        }
        //获取写锁的个数
        public int getHoldCount() {
            return sync.getWriteHoldCount();
        }
    }

内部有一属性为sync,是从外部类继承过来,使用同一syn。使用独占锁,至于方法与ReentrantLock类似,同名方法作用一样,实现都是调用AQS以及Syn及子类方法,再次不赘述。

三、构造器
ReentrantReadWriteLock对外提供两个构造器:

public ReentrantReadWriteLock() {
    this(false);
}
public ReentrantReadWriteLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
    readerLock = new ReadLock(this);
    writerLock = new WriteLock(this);
}

protected ReadLock(ReentrantReadWriteLock lock) {
    sync = lock.sync;
}
protected WriteLock(ReentrantReadWriteLock lock) {
    sync = lock.sync;
}

public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }
  1. ReentrantReadWriteLock(),默认构造器,默认使用非公平锁,故上文中描述该类默认使用非公平锁
  2. ReentrantReadWriteLock(boolean fair),带参构造器,传入true则是公平锁,false是非公平锁

四、对外提供方法
ReentrantReadWriteLock提供了一系列方法,都是基于AQS以及上述Sync系列静态内部类实现,实现原理较简单,作用见注释,不一一详述。

// 返回当前拥有写入锁的线程,如果没有这样的线程,则返回 null。
protected Thread getOwner()
// 返回一个 collection,它包含可能正在等待获取读取锁的线程。
protected Collection<Thread> getQueuedReaderThreads()
// 返回一个 collection,它包含可能正在等待获取读取或写入锁的线程。
protected Collection<Thread> getQueuedThreads()
// 返回一个 collection,它包含可能正在等待获取写入锁的线程。
protected Collection<Thread> getQueuedWriterThreads()
// 返回等待获取读取或写入锁的线程估计数目。
int getQueueLength()
// 查询当前线程在此锁上保持的重入读取锁数量。
int getReadHoldCount()
// 查询为此锁保持的读取锁数量。
int getReadLockCount()
// 返回一个 collection,它包含可能正在等待与写入锁相关的给定条件的那些线程。
protected Collection<Thread> getWaitingThreads(Condition condition)
// 返回正等待与写入锁相关的给定条件的线程估计数目。
int getWaitQueueLength(Condition condition)
// 查询当前线程在此锁上保持的重入写入锁数量。
int getWriteHoldCount()
// 查询是否给定线程正在等待获取读取或写入锁。
boolean hasQueuedThread(Thread thread)
// 查询是否所有的线程正在等待获取读取或写入锁。
boolean hasQueuedThreads()
// 查询是否有些线程正在等待与写入锁有关的给定条件。
boolean hasWaiters(Condition condition)
// 如果此锁将公平性设置为 ture,则返回 trueboolean isFair()
// 查询是否某个线程保持了写入锁。
boolean isWriteLocked()
// 查询当前线程是否保持了写入锁。
boolean isWriteLockedByCurrentThread()
// 返回用于读取操作的锁。
ReentrantReadWriteLock.ReadLock readLock()
// 返回用于写入操作的锁。
ReentrantReadWriteLock.WriteLock writeLock()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值