javalock(七)AQS派生类ReentrantLock

发布于:2024-12-21 ⋅ 阅读:(150) ⋅ 点赞:(0)

总结:
ReentrantLock是一把可重入的独占锁,即一把同一时刻只允许一个线程拥有的写锁,虽然只允许一个线程同时持有,但是没有限制一个线程持有次数。ReentrantLock用两个变量来表示锁资源{锁持有计数(state),锁拥有者(owner)},state不为0就表示有人持有了锁,然后再判断owner是不是自己,如果是则说明是自己获得了锁,允许再次获得锁,反之不允许

import java.util.concurrent.TimeUnit;
import java.util.Collection;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
//是一把独占锁
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;

    private final Sync sync;

    //sync是基类,从此基础上会派生出公平和非公平方式
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        //分公平和非公平方式,所以是抽象方法
        abstract void lock();

        //非公平方式的获取独占锁tryAcquire,acquires参数为1
        final boolean nonfairTryAcquire(int acquires) {
            //获取当前线程,可重入的独占锁,所以要记录锁拥有者
            final Thread current = Thread.currentThread();
            //获取锁状态,state表示获取了几次锁
            int c = getState();
            //快速判断一下是否有人获取了锁,0表没人
            if (c == 0) {
                //如果没人获取锁,则尝试通过cas抢占锁
                if (compareAndSetState(0, acquires)) {
                    //如果抢占成功,则记录锁的拥有者为当前线程
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //不为0表有人已经获得了锁,所以就判断是不是自己获得了锁
            else if (current == getExclusiveOwnerThread()) {
                //如果是自己获得了锁,则锁计数+acquires,这里acquires=1
                int nextc = c + acquires;
                //如果计数超过了int_max就表示获取锁次数太多了
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                //这里设置state,不需要使用cas,因为此时本线程已经获得了锁,是重入
                setState(nextc);
                return true;
            }
            //否则走到这里表明有人获得了锁,且不是自己就返回获取锁失败
            return false;
        }

        //tryRelease:释放锁资源,释放锁资源没有公平不公平一说
        protected final boolean tryRelease(int releases) {
            //释放锁资源就是锁计数-releases,releases这里等于1
            int c = getState() - releases;
            //如果不是自己拥有锁,就抛异常,因为必须拥有锁才能释放
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            //如果释放后计数归0,则表明本线程已释放全部锁
            if (c == 0) {
                free = true;
                //所以把锁的拥有者设置为null
                setExclusiveOwnerThread(null);
            }
            //注意,此时state还是不为0的,所以也就是说其他线程看到的state不为0
            //也就是说当前线程还拥有锁,所以可以无保护设置
            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() {
            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
        }
    }

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

        //非公平lock:就是在入队之前就检测一次能否获得锁,如果能,就直接获取锁而不用入队排队等待
        final void lock() {
            //快速尝试能否获得锁:如果state状态为0,并且本线程成功通过cas设置state,则成功获得所
            if (compareAndSetState(0, 1))
                //成功获得锁就设置一下锁拥有者为自己
                setExclusiveOwnerThread(Thread.currentThread());
            else
                //如果快速获取失败,则走重逻辑获取锁:
                // 先入队排队,直到本线程成为head.next,然后本线程再尝试获取锁
                acquire(1);
        }

        //tryAcquire:就是对nonfairTryAcquire的简单封装
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    //公平方式获得锁:就是先排队,等他前面的都获得了锁,然后再轮到他
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        //就是直接调用aqs的acquire,把当前线程的node添加到sync list末尾,
        // 直到本node成为head.next才开始尝试
        final void lock() {
            //注意:aqs的acquire函数一进去就会调用tryAcquire尝试快速获得锁
            //所以为了实现公平锁:即先来先获取锁
            //那么tryAcquire的逻辑必须是:如果检测到AQS的sync list中有线程在排队
            //那么就直接返回false,也就是说只要有人在排队,后来者就获取锁失败
            acquire(1);
        }

        //公平方式:如果有人排队就返回false
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            //先资源是否被人持有
            if (c == 0) {
                //如果锁空闲则判断有没有人在排队,如果有,则返回false
                //hasQueuedPredecessor函数是不准确的
                //也就是说可能在判断的时候有其他人刚好也判断并取了锁
                //这个没关系的
                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;
            }
            //否则返回false表示获取失败
            return false;
        }
    }

    public ReentrantLock() {
        sync = new NonfairSync();
    }

    //创建ReentrantLock,默认非公平锁
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

    //ReentrantLock.lock就是调用sync.lock
    public void lock() {
        sync.lock();
    }

    //获取锁,如果发生中断就抛异常
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    //ReentrantLock导出的tryLock方法,表示尝试获取锁,如果获取不到就直接返回false
    //也就是说这里直接调用tryAcquire尝试获取锁,而tryAcquire是不会阻塞的
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

    //尝试获取锁,发生中断就抛异常,超时就返回false
    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

    //释放锁,前面说过了,就是锁计数-1,如果为0,就清空锁拥有者
    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();
    }

    //判断是否有人在排队等待获取锁
    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);
    }


    public String toString() {
        Thread o = sync.getOwner();
        return super.toString() + ((o == null) ?
                "[Unlocked]" :
                "[Locked by thread " + o.getName() + "]");
    }
    //总结下来就是ReentrantLock的condition就是直接用的AQS的condition
}

   

网站公告

今日签到

点亮在社区的每一天
去签到