ReentrantReadWriteLock源码分析

前言

        ReentrantReadWriteLock是Java中的一种读写锁,它允许多个线程同时读取共享资源,但是只允许一个线程进行写入操作。在读多写少的场景中,读写锁可以提高程序的并发性能。

ReentrantReadWriteLock的实现是基于AbstractQueuedSynchronizer (AQS)的同步器实现的。通过AQS的内部状态和线程的协作,ReentrantReadWriteLock实现了对共享资源的读取和写入操作的互斥和排他。

源码实现:

1. 构造函数

ReentrantReadWriteLock有两个构造函数:
 

public ReentrantReadWriteLock() {
    this(false);
}

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

其中,sync是同步器实例,根据fair参数可以选择公平或非公平模式的同步器。

2. 锁的表示

        static final int SHARED_SHIFT   = 16;
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

        ReentrantReadWriteLock用一个16位的无符号数来表示锁的占用,其他,前8bit表示读锁,后8bit表示写锁。


        /** Returns the number of shared holds represented in count  */
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
        /** Returns the number of exclusive holds represented in count  */
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

3. 同步器实现

ReentrantReadWriteLock的同步器实现分为两种:公平模式和非公平模式。两种模式的区别在于线程获取锁的顺序不同,公平模式下线程按照请求的顺序获取锁,非公平模式下线程可以插队获取锁。

NonfairSync是非公平模式下的同步器实现。

static final class NonfairSync extends Sync {
    private static final long serialVersionUID = -2694183684443567898L;

    final void writerAcquire(int arg) {
        if (compareAndSetState(0, arg))
            exclusiveOwnerThread = Thread.currentThread();
        else
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg);
    }

    final boolean tryWriterAcquire(int arg) {
        if (getState() != 0)
            return false;
        if (compareAndSetState(0, arg)) {
            exclusiveOwnerThread = Thread.currentThread();
            return true;
        }
        return false;
    }

    final boolean tryWriterRelease() {
        if (!isHeldExclusively())
            throw new IllegalMonitorStateException();
        exclusiveOwnerThread = null;
        setState(0);
        return true;
    }

    final boolean tryReaderAcquire() {
        for (;;) {
            int c = getState();
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != Thread.currentThread())
                return false;
            int nextc = c + SHARED_UNIT;
            if (nextc < c)
                throw new Error("Maximum lock count exceeded");
            if (compareAndSetState(c, nextc))
                return true;
        }
    }

    final boolean tryReaderRelease() {
        for (;;) {
            int c = getState();
            int nextc = c - SHARED_UNIT;
            if (compareAndSetState(c, nextc))
                return nextc == 0;
        }
    }

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

FairSync是公平模式下的同步器实现。
 

static final class FairSync extends Sync {
    private static final long serialVersionUID = -2274990926593161451L;

    final void writerAcquire(int arg) {
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg);
    }

    final boolean tryWriterAcquire(int arg) {
        Thread current = Thread.currentThread();
        int c = getState();
        if (c != 0) {
            int w = exclusiveCount(c);
            if (w == 0 || current != getExclusiveOwnerThread())
                return false;
            if (w + exclusiveCount(arg) > MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            setState(c + arg);
            return true;
        }
        if (!hasQueuedPredecessors() && compareAndSetState(0, arg)) {
            exclusiveOwnerThread = current;
            return true;
        }
        return false;
    }

    final boolean tryWriterRelease() {
        Thread current = Thread.currentThread();
        if (getState() == 0)
            throw new IllegalMonitorStateException();
        if (getExclusiveOwnerThread() != current)
            throw new IllegalMonitorStateException();
        int nextc = getState() - 1;
        boolean free = exclusiveCount(nextc) == 0;
        setState(nextc);
        if (free)
            exclusiveOwnerThread = null;
        return free;
    }

    final boolean tryReaderAcquire() {
        Thread current = Thread.currentThread();
        for (;;) {
            Node last = tail;
            Node p = head;
            while (p != last) {
                if (!isBeforeSplice(p) &&
                    p.thread != current)
                    return false;
                p = p.next;
            }
            int c = getState();
            int nextc = c + SHARED_UNIT;
            if (nextc < c)
                throw new Error("Maximum lock count exceeded");
            if (compareAndSetState(c, nextc)) {
                boolean first = sharedCount(c) == 0;
                if (!first)
                    return true;
                if (firstReader == null)
                    firstReader = current;
                else if (firstReader != current)
                    nodeWaiterCount = FULL_SHUTDOWN;
                return true;
            }
        }
    }

    final boolean tryReaderRelease() {
        Thread current = Thread.currentThread();
        for (;;) {
            int c = getState();
            int nextc = c - SHARED_UNIT;
            if (compareAndSetState(c, nextc)) {
                if (nextc == 0) {
                    firstReader = null;
                    if (nodeWaiterCount == 2)
                        unparkSuccessor(head);
                } else if (firstReader != null && firstReader != current) {
                    nodeWaiterCount = FULL_SHUTDOWN;
                }
                return true;
            }
        }
    }

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

4. 读写锁实现

对于ReentrantReadWriteLock来说,最重要的是提供读锁和写锁的方法。下面是读锁和写锁的实现:
 

public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {

    static final class ReadLock extends Sync implements Lock {
        private static final long serialVersionUID = -5992448646407690164L;

        ReadLock(ReentrantReadWriteLock lock) {
            super(lock);
        }

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

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

        public boolean tryLock() {
            return sync.tryAcquireShared(1) >= 0;
        }

        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();
        }
    }

    static final class WriteLock extends Sync implements Lock {
        private static final long serialVersionUID = -4992448646407690164L;

        WriteLock(ReentrantReadWriteLock lock) {
            super(lock);
        }

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

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

        public boolean tryLock() {
            return sync.tryAcquire(1);
        }

        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() {
            throw new UnsupportedOperationException();
        }
    }

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

    public ReentrantReadWriteLock() {
        this(false);
    }

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

    public Lock readLock() {
        return readerLock;
    }

    public Lock writeLock() {
        return writerLock;
    }
}

读锁和写锁分别继承了Sync类,通过调用Sync类的acquireShared、tryAcquireShared、releaseShared等方法实现了读锁和写锁的功能。

总结

ReentrantReadWriteLock是一种读写锁,它允许多个线程同时读取共享资源,但是只允许一个线程进行写入操作。ReentrantReadWriteLock的实现是基于AbstractQueuedSynchronizer(AQS)的同步器实现的,通过AQS的内部状态和线程的协作,ReentrantReadWriteLock实现了对共享资源的读取和写入操作的互斥和排他。在使用ReentrantReadWriteLock时需要注意读多写少的场景,否则可能出现写操作被饥饿。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值