美文网首页
ReentantLock核心代码

ReentantLock核心代码

作者: qizhongju | 来源:发表于2020-04-22 18:15 被阅读0次

    Lock接口

    Reentrant实现了Lock接口,Lock接口主要定义了如下几个方法:

    //加锁
    void lock();
    //获取锁
    boolearn tryLock();
    //获取锁(设置超时等待时间)
    boolearn tryLock(long time, TimeUnit unit) throw InterruptedException;
    //释放锁
    void unlock();
    

    ReentrantLock结构

    ReentrantLock结构

    默认构造创建的是一个非公平锁,可以通过参数控制创建的是公平的还是非公平的;

        //默认的构造为非公平重入锁
        public ReentrantLock() {
            sync = new NonfairSync();
        }
        
        //根据fair参数判断创建的是公平锁还是非公平
        public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    

    公平锁:按照线程先来后到顺序获取锁,后到的线程只能等前面的线程都获取锁完毕才执行获取锁的操作,执行有序
    非公平锁:不按照线程先来后到的时间顺序进行竞争锁,后到的线程也能够获取到锁

    ReentrantLock内部类:NonfairSync,FairSync

    Reentrant都是通过NonfairSync和FairSync来实现锁的功能,它俩的父类Sync则继承了AbstractQueuedSynchronizer,AQS是JUC框架核心。

    加锁lock()

    //公平锁
    //static final class FairSync extends Sync
    final void lock() {
      acquire(1);
    }
    
    //非公平锁
    // static final class NonfairSync extends Sync {
    final void lock() {
      //CAS更新同步状态值state,锁占有线程设置为当前线程
      if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
      else
        acquire(1);
    }
    

    先看一下acquire(1)方法,此方法定义在Sync的父类AbstractQueuedSynchronizer中

    //AbstractQueuedSynchronizer.java
    //获取锁,此部分逻辑定义在父类中,NonfairSync和FairSync通用,只是tryAcquire(arg) 有不同的实现
    public final void acquire(int arg) {
            //获取锁失败  &&  acquireQueued方法会将线程排队到队列并且返回线程是否需要中断
            if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
                selfInterrupt();
    }
    
    /**
    * 中断当前线程
    **/
    static void selfInterrupt() {
            Thread.currentThread().interrupt();
    }
    

    公平锁的tryAcquire实现

    //static final class FairSync extends Sync
    //尝试获取锁的逻辑(公平锁),获取成功返回true,失败返回false
    protected final boolean tryAcquire(int acquires) {
        //获取当前线程
        final Thread current = Thread.currentThread();
        //获取同步状态的当前值
        int c = getState();
        if (c == 0) {
            //判断前面是否有排队的线程,没有的话CAS设置线程的state值为1
            //与非公平锁的获取锁实现唯一区别的地方
            //非公平锁不需要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;
    }
    

    非公平锁的tryAcquire实现

    //Sync object for non-fair locks
     protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
     }
    
    //nonfairTryAcquire实现在父类Sync中
    final boolean nonfairTryAcquire(int acquires) {
        //获取当前线程
        final Thread current = Thread.currentThread();
        //获取同步状态值
        int c = getState();
        if (c == 0) {
            //与公平锁的获取锁实现唯一区别的地方
            //公平锁要hasQueuedPredecessors() 判断前面是否有排队的线程
            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;
    }
    
    

    tryAcquire(arg)返回false的话,执行acquireQueued进行添加到队列,此方法定义在AbstractQueuedSynchronizer中,参数需要addWaiter(Node.EXCLUSIVE)返回的Node。

    //AbstractQueuedSynchronizer.java
    /**
    * 为当前线程和给定模式创建和排队节点
    **/
    private Node addWaiter(Node mode) {
        //创建当前线程节点
        Node node = new Node(Thread.currentThread(), mode);
        Node pred = tail;
        if (pred != null) {
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }
    
    /**
    * 尝试排队
    **/
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                //前面无排队线程 && 获取锁成功
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                //获取锁失败后暂停线程
                if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) 
                  interrupted = true;
            }
        } finally {
            if (failed) 
              cancelAcquire(node);
        }
    }
    

    解锁lock()

    解锁方法定义在AbstractQueuedSynchronizer中,实现在ReentrantLock的内部类Sync中

    //ReentrantLock.java
    public void unlock() {
        sync.release(1);
    }
    
    //AbstractQueuedSynchronizer.java
    public final boolean release(int arg) {
        //尝试获取锁
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0) 
                //唤醒等待的线程获取锁
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
    
    //ReentrantLock.Sync
    protected final boolean tryRelease(int releases) {
        //计算状态值
        int c = getState() - releases;
        //当前线程没有占有锁
        if (Thread.currentThread() != getExclusiveOwnerThread()) 
            throw new IllegalMonitorStateException();
        boolean free = false;
        if (c == 0) {
            //释放锁成功
            free = true;
            setExclusiveOwnerThread(null);
        }
        //更新状态值
        setState(c);
        return free;
    }
    

    相关文章

      网友评论

          本文标题:ReentantLock核心代码

          本文链接:https://www.haomeiwen.com/subject/hnormhtx.html