并发包独占锁ReentrantLock与读写锁ReentrantReadWriteLock

Posted wqff-biubiu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发包独占锁ReentrantLock与读写锁ReentrantReadWriteLock相关的知识,希望对你有一定的参考价值。

两个锁都是依赖AQS实现的,方法基本是Sync的封装,主要看Sync的设计实现,

一、可重入独占锁ReentrantLock

1.静态内部抽象类Sync

    //继承AQS
  abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        /**
         * 延迟到子类实现(公平锁与非公平锁)
         */
        abstract void lock();

        /**
         * 尝试获取非公平锁
         */
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //计数器state == 0:锁未被持有,计数器原子性自增并设置当前线程为持有者
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                //计数器state != 0:锁被当前线程为持有者,计数器state增加(可重入锁)
                int nextc = c + acquires;
                if (nextc < 0) // 可重入次数溢出跑错
                    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) {
                //计数器state == 0:释放锁,设置持有者为null
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

        protected final boolean isHeldExclusively() {
            //判断当前线程是否为锁的持有者
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            //创建条件变量
            return new ConditionObject();
        }

        // Methods relayed from outer class

        final Thread getOwner() {
            //获取当前锁的持有线程
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        final int getHoldCount() {
            //当前线程为锁的持有者返回计数器state值,不是锁的持有者返回0
            return isHeldExclusively() ? getState() : 0;
        }

        final boolean isLocked() {
            //锁是否被持有
            return getState() != 0;
        }

        /**
         * 创建反序列化实例,重置计数器值,锁状态初始化
         */
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

继承Sync的非公平锁NonfairSync与公平锁FairSync

    /**
     * 非公平锁
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                //当前计数器state == 0即锁未被持有时,state自增且直接设置当前线程为锁持有者(未检查阻塞队列,破坏FIFO)
                setExclusiveOwnerThread(Thread.currentThread());
            else
                //当前计数器state != 0即锁被持有时,调用AQS的独占模式获取资源,会调用下面的tryAcquire尝试获取锁
                acquire(1);
        }

        //acquire方法中tryAcquire实现,尝试获取锁,若锁未被持有,直接获取锁,不入阻塞队列,破坏FIFO
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    /**
     * 公平锁
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * 公平锁尝试获取资源,锁未被持有时,先队列,后当前线程
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //计数器state == 0,锁未被持有
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    //AQS阻塞队列为空或者当前线程是阻塞队列头结点的后继节点,直接设置当前线程为锁的持有者,计数器state自增
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                //计数器state != 0.锁被持有且持有者是当前线程,计数器state自增
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

2.ReentrantLock的变量与构造方法

    private final Sync sync;//实际的锁对象

    public ReentrantLock() {
        sync = new NonfairSync();//无参构造函数默认非公平锁 == ReentrantLock(false)
    }

    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();//可指定公平锁还是非公平锁
    }

3.ReentrantLock的方法:都是Sync的封装

    //尝试获取锁
    public void lock() {
        sync.lock();
    }

    //尝试获取锁,不忽略中断,中断抛错
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    //尝试获取锁
    public boolean tryLock() {
        return sync.nonfairTryAcquire(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() {
        return sync.newCondition();
    }

    //返回锁的重入数,不是锁持有者则返回0
    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();
    }


    //判断AQS队列是否为空
    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    //
    public final boolean hasQueuedThread(Thread thread) {
        return sync.isQueued(thread);
    }

    public final int getQueueLength() {
        return sync.getQueueLength();
    }

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

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

以上是关于并发包独占锁ReentrantLock与读写锁ReentrantReadWriteLock的主要内容,如果未能解决你的问题,请参考以下文章

Java 并发编程 进阶 -- Java并发包中锁原理剖析(LockSupport抽象同步队列AQS独占锁ReentrantLock读写锁ReentrantReadWriteLock)

Java中juc并发包下的Condition接口与ReentrantLock对象锁实现线程通信

并发编程—独占锁和共享锁

7.ReadWriteLock接口及其实现ReentrantReadWriteLock

JDK并发包

java并发-锁-ReentrantLock(重入锁)和ReentrantReadWriteLock(读写锁)