实战Java高并发程序设计之ReentrantLock(二)

来源:互联网 发布:linux下usb通讯编程 编辑:程序博客网 时间:2024/05/29 04:48

前面讲到了ReentranLock的基本使用,现在来看看它的底层实现.

先看ReentrantLok的UML类图(图片来自:http://www.cnblogs.com/skywang12345/p/3496147.html)


ReentrantLock实现了Lock接口.内部维持着一个Sync对象.

    /**     * 该锁基于同步控制. 分为公平锁和非公平锁.      * 使用AQS状态来表示锁上的保留数量.0表示无锁     */    abstract static class Sync extends AbstractQueuedSynchronizer {        private static final long serialVersionUID = -5179523762034025860L;        //抽象的lock方法,交给子类去实现        abstract void lock();        /**         * 执行不公平的tryLock.  tryAcquire在子类中实现, 都需要不公平锁去尝试tryLock()         */        final boolean nonfairTryAcquire(int acquires) {            final Thread current = Thread.currentThread();            //获取当前同步的状态值            int c = getState();            //0表示该锁处于可获取状态            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;            //状态为0时,表示无锁            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() {        //状态为0表示没有锁,返回空.            return getState() == 0 ? null : getExclusiveOwnerThread();        }                /**         * 获取锁的数量         */        final int getHoldCount() {            return isHeldExclusively() ? getState() : 0;        }                /**         * 判断是否被锁         */        final boolean isLocked() {        //状态不为0表示有锁            return getState() != 0;        }        /**         * 从流重构实例(即反序列化).         */        private void readObject(java.io.ObjectInputStream s)            throws java.io.IOException, ClassNotFoundException {            s.defaultReadObject();            setState(0); // 重置无锁状态        }    }
FairSync和NonFairSync分别继承了Sync类,下面来看看它们的分别实现

/**     * 非公平锁     */    static final class NonfairSync extends Sync {        private static final long serialVersionUID = 7316153563782823691L;        /**         * 非公平锁的lock会无视等待队列,直接去尝试获取锁,不成功则在调用acquire()尝试获取锁         */        final void lock() {        //如果AQS的状态为0,则将状态变为1,表示获得一把锁.然后设置独占锁所持有的线程为当前线程            if (compareAndSetState(0, 1))                setExclusiveOwnerThread(Thread.currentThread());            else                acquire(1);        }                /**         * 尝试获取锁         */        protected final boolean tryAcquire(int acquires) {        //调用Sync的nonfairTryAcquire(args)方法            return nonfairTryAcquire(acquires);        }    }    /**     * 公平锁     */    static final class FairSync extends Sync {        private static final long serialVersionUID = -3000897897090466540L;                /**         * 获取一把锁         */        final void lock() {            acquire(1);        }        /**         * 去尝试获取锁,获取成功则设置锁状态并返回true,否则返回false         */        protected final boolean tryAcquire(int acquires) {            final Thread current = Thread.currentThread();            int c = getState();            if (c == 0) {            //hasQueuedPredecessors()方法是查询队列中是否有比当前线程等待更长时间的线程                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;        }    }
可以看出公平锁和非公平尝试获取锁的不同之处就体现在if(c == 0 )中

// -----非公平锁-----if(c==0){if (compareAndSetState(0, acquires)) {etExclusiveOwnerThread(current);return true;}}// -------公平锁-----if(c==0){           if (!hasQueuedPredecessors() &&                compareAndSetState(0, acquires)) {                setExclusiveOwnerThread(current);                return true;        }    }
ReentrantLock类的其他方法:

/** * 无参构造 */public ReentrantLock() {sync = new NonfairSync();}/** * 构建公平锁或非公平锁 */public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}/** * 获取锁:如果锁没有被另一个线程占用并且立即返回,则将锁定计数设置为1 * 如果当前线程已经保持锁定,则保持计数增加1,该方法立即返回。 * 如果锁被另一个线程保持,则当前线程将被禁用以进行线程调度,并处于休眠状态,直到锁定被获取为止,此时锁定保持计数被设置为1. */public void lock() {sync.lock();}/** * 获取锁,除非当前线程中断 */public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}/** * 如果没有被另一个线程占用,则获取该锁,并立即返回该值.设置锁数量为1 */public boolean tryLock() {return sync.nonfairTryAcquire(1);}/** * 尝试在指定时间内获取锁 * 指定时间内没获取到返回false */public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));}/** * 释放一把锁 */public void unlock() {sync.release(1);}/** * 构建一个Condition实例 */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();}/** * 查询给定的线程是否在等待该锁 */public final boolean hasQueuedThread(Thread thread) {return sync.isQueued(thread);}

参考文献:

【Java并发编程实战】—–“J.U.C”:ReentrantLock之二lock方法分析

源码来自JDK1.8,注释来自自己翻译,不足自出希望指正

0 0
原创粉丝点击