Java并发学习笔记16 AQS 之 ReentrantReadWriteLock

bilibili-Java并发学习笔记16 AQS 之 ReentrantReadWriteLock

基于 java 1.8.0

P48_可重入读写锁底层源码分析及思想探究

// ReadWriteLock 使用示例
package new_package.thread.p45;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.IntStream;

public class ReadWriteLockTest {

    ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public void method1() {
        try {
            readWriteLock.readLock().lock();
            System.out.println("method1");
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            readWriteLock.readLock().unlock();
        }
    }

    public void method2() {
        try {
            readWriteLock.writeLock().lock();
            System.out.println("method2");
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }

    public static void main(String[] args) {
        ReadWriteLockTest demo = new ReadWriteLockTest();
        IntStream.range(0, 10).forEach(k -> new Thread(() -> {
            demo.method2();
        }).start());
    }
}
  1. 公平锁与非公平锁

类似 ReentrantLock ,在构造器中指定是否为公平锁,默认非公平模式;

// 默认非公平模式
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

// 指定为公平模式
ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
    /** Inner class providing readlock */
    private final ReentrantReadWriteLock.ReadLock readerLock;

    /** Inner class providing writelock */
    private final ReentrantReadWriteLock.WriteLock writerLock;

    /** Performs all synchronization mechanics */
    final Sync sync;

    public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
        readerLock = new ReadLock(this);
        writerLock = new WriteLock(this);
    }
    // 关于同步器

    /**
     * ReentrantReadWriteLock 的内部类,同步器的实现
     * 子类有公平版本和非公平版本
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        ///
    }

    /**
     * 非公平版本的 Sync
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -8159625535654395037L;
        final boolean writerShouldBlock() {
            return false; // writers can always barge
        }
        final boolean readerShouldBlock() {
            /* As a heuristic to avoid indefinite writer starvation,
             * block if the thread that momentarily appears to be head
             * of queue, if one exists, is a waiting writer.  This is
             * only a probabilistic effect since a new reader will not
             * block if there is a waiting writer behind other enabled
             * readers that have not yet drained from the queue.
             */
            return apparentlyFirstQueuedIsExclusive();
        }
    }

    /**
     * 公平版本的 Sync
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -2274990926593161451L;
        final boolean writerShouldBlock() {
            return hasQueuedPredecessors();
        }
        final boolean readerShouldBlock() {
            return hasQueuedPredecessors();
        }
    }
    // 关于读写锁实现

    /**
     * ReentrantReadWriteLock 的内部类
     * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
     */
    public static class ReadLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -5992448646407690164L;
        private final Sync sync;

        /**
         * Constructor for use by subclasses
         *
         * @param lock the outer lock object
         * @throws NullPointerException if the lock is null
         */
        protected ReadLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        // ...
    }

    /**
     * ReentrantReadWriteLock 的内部类
     * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
     */
    public static class WriteLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -4992448646407690164L;
        private final Sync sync;

        /**
         * Constructor for use by subclasses
         *
         * @param lock the outer lock object
         * @throws NullPointerException if the lock is null
         */
        protected WriteLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        // ...
    }
  1. 读锁的上锁
    readWriteLock.readLock().lock();
    // 实现
    public void lock() {
        sync.acquireShared(1);
    }
    public final void acquireShared(int arg) {
        // 尝试获取共享锁
        if (tryAcquireShared(arg) < 0)
            doAcquireShared(arg);
    }
        protected final int tryAcquireShared(int unused) {
            /*
             * Walkthrough:
             * 1. 如果另一个线程持有写锁,则失败。
             * 2. 否则,此线程符合 lock wrt state 的条件,
             *    因此询问它是否应该因为队列策略而阻塞。
             *    如果没有,尝试通过大小写状态和更新计数来授予。
             *    注意,step不检查可重入获取,它被推迟到完整版本,
             *    以避免在更典型的不可重入情况下检查保留计数。
             * 3. 如果步骤2失败是因为线程明显不合格、CAS失败或计数饱和,
             *    则使用完整的重试循环链到版本。
             */
            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) {
                    // 共享锁的占有数不为0
                    // 第一个获取到此共享锁的线程是本线程
                    firstReaderHoldCount++;
                } else {
                    // 共享锁的占有数不为0 ,且 firstReader 不是当前线程
                    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);
        }
        // int 类型占 4 byte,占 32 bit (一半就是 16 bit)
        static final int SHARED_SHIFT   = 16;
        // 1 左移 16 位      :00000000 00000001 00000000 00000000
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
        // (1 左移 16 位) -1 :00000000 00000000 11111111 11111111
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

        /**
         * 返回以count表示的共享保留数
         * state 无逻辑右移 16 位,即 state 的高16位
         */
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
        /**
         * 返回以count表示的独占保留数
         * state & 00000000 00000000 11111111 11111111 即:state 的低16位
         */
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

// <<  表示左移,不分正负数,低位补0;
// >>  表示右移,如果该数为正,则高位补0,若为负数,则高位补1;
// >>> 表示无符号右移,也叫逻辑右移,即无论该数为正负,都是高位补0
    // Fair version of Sync
    final boolean readerShouldBlock() {
        // 等待队列中是否还有前置节点
        return hasQueuedPredecessors();
    }

    // Nonfair version of Sync
    final boolean readerShouldBlock() {
        // 
        return apparentlyFirstQueuedIsExclusive();
    }

    final boolean apparentlyFirstQueuedIsExclusive() {
        Node h, s;
        return (h = head) != null &&
            (s = h.next)  != null &&
            !s.isShared()         &&
            s.thread != null;
    }
  1. 写锁的上锁
    readWriteLock.writeLock().lock();
    public void lock() {
        sync.acquire(1);
    }
    public final void acquire(int arg) {
        // 尝试获取独占锁
        // 若获取失败,则加入等待队列
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
    // Sync in ReentrantReadWriteLock 的实现
    protected final boolean tryAcquire(int acquires) {
        /*
            * Walkthrough:
            * 1. 如果读计数非零或写入计数非零且所有者是不同的线程,则失败。
            * 2. 如果计数饱和,则失败。(只有当count已非零时才会发生这种情况。)
            * 3. 否则,如果这个线程是可重入的获取或队列策略允许的话,它就有资格被锁定。如果是,请更新状态并设置所有者。
            */
        Thread current = Thread.currentThread();

        // state 的状态
        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())
                // 有共享锁占有
                // 当前独占锁不是当前线程占有的
                return false;
            if (w + exclusiveCount(acquires) > MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            // Reentrant acquire
            setState(c + acquires);
            return true;
        }
        if (writerShouldBlock() ||
            !compareAndSetState(c, c + acquires))
            return false;
        setExclusiveOwnerThread(current);
        return true;
    }

P49_可重入读写锁的共享锁释放源码解析

  1. 读锁的释放
    readWriteLock.readLock().unlock();
    public void unlock() {
        sync.releaseShared(1);
    }
    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }
    protected final boolean tryReleaseShared(int unused) {
        Thread current = Thread.currentThread();
        if (firstReader == current) {
            // assert firstReaderHoldCount > 0;
            if (firstReaderHoldCount == 1)
                firstReader = null;
            else
                firstReaderHoldCount--;
        } else {
            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)
                    throw unmatchedUnlockException();
            }
            --rh.count;
        }
        for (;;) {
            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;
        }
    }
  1. 写锁的释放
    readWriteLock.writeLock().unlock();
    public void unlock() {
        sync.release(1);
    }
    // AQS
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
        protected final boolean tryRelease(int releases) {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            int nextc = getState() - releases;
            boolean free = exclusiveCount(nextc) == 0;
            if (free)
                setExclusiveOwnerThread(null);
            setState(nextc);
            return free;
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值