java多线程随手记——ReentrantLock的公平锁与非公平锁

         ReentrantLock是concurrent包中,实现的一个锁,下面,我们将对其源码进行分析,以期获得更为有价值的内容。

         我们可以按照ReentrantLock的使用方式,来慢慢解析其源码构成。

         正如上一章Java多线程随手记——各种锁中的CODE使用的方式,首先我们需要初始化ReentrantLock对象。

     /**
     * Creates an instance of {@code ReentrantLock}.
     * This is equivalent to using {@code ReentrantLock(false)}.
     */
    public ReentrantLock() {
        sync = new NonfairSync();
    }
    /**
     * Creates an instance of {@code ReentrantLock} with the
     * given fairness policy.
     *
     * @param fair {@code true} if this lock should use a fair ordering policy
     */
    public ReentrantLock(boolean fair) {
        sync = (fair)? new FairSync() : new NonfairSync();
    }

         从这里可以看到,ReentrantLock实现了公平锁和非公平锁两种方式,首先,我们先把两种实现的思路描述下,然后再看具体实现。

         公平锁:看名字就特别和谐,大家都一起排队WC,队伍中轮到谁了谁就去。

         非公平锁:这就是特别暴力了,大家都憋不住,队伍排是排,但是只要厕所里的人一出来,不管队伍顺序,靠拳头说话,谁抢到了算谁的。

         接下来,我们开始着手具体实现。

         公平锁:

 /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (isFirst(current) &&
                    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;
        }

         首先,看看state是否为0,也就是占用线程已经全部unlock掉,那么再看看自己是不是处于队列的第一个,compareAndSetState()同时检查占用状态,并且修改state值(这是一个底层的CAS原子操作,我是把它理解为类似操作系统中的P操作)。current == getExclusiveOwnerThread()后面便是完成了可重入锁的功效了,当前线程进入lock再这之上再加锁+acquires,之后的章节会详细介绍可重入锁的用途。 

         非公平锁:

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

       这个非公平锁就野蛮的很,只要看到C为0了,就开抢,不管自己队列顺序,直接做CAS操作,谁先抢到谁就把state这门给关了,让别人进不来。

  下面,我们回头看看调用tryAcquire 的acquire方法

    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

可以看到不管公平锁还是非公平锁,都是如果无法获取到当前锁,那么将进入队列中,同时如果满足阻塞条件,那么该线程将会被interrupt掉,直到等待被唤醒。

AbstractQueuedSynchronized 这个类的实现还是挺复杂的,同时它为了该Queue可以并发使用了一个双重检测的设计,打算新开个章节来详细叙述。

 

下一章节:AbstractQueuedSynchronized类源码分析

    

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值