美文网首页
ReentrantLock 解析

ReentrantLock 解析

作者: Wi1ls努力努力再努力 | 来源:发表于2019-04-26 22:18 被阅读0次
     public ReentrantLock() {
            sync = new NonfairSync();
        }
     public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    

    ReentrantLock 有两种实现,公平锁 FairSync 和非公平锁NonfairSync;

    用法

    ReentrantLock lock = new ReentrantLock(true/false);
    
    public void lockMethod(){
      lock.lock();
      ...
      lock.unlock();
    }
    
    

    则 lock.lock()和lock.unlock()则为获得锁和释放锁。

    @ReentrantLock
    public void lock(){
      sync.lock();
    }
    
    //以公平锁分析
    @FairSync
    final void lock(){
      acquire(1);
    }
    
    @AbstractQueuedSynchronizer
    public final void acquire(int arg){
      if(!tryAcquire(args) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg)){
        selfInterrupt();
      }
    }
    
    @FairSync
     protected final boolean tryAcquire(int acquires) {
                //获取当前线程
                final Thread current = Thread.currentThread();
                //获得 volatile state,如果是第一个进来的线程c 为 0,后面进来的线程如果锁还没有释放的话, c 为 1 
                int c = getState();
                if (c == 0) {
                    //可以获得锁的线程,并且 CAS 操作设置 state 为 1
                    if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {
                        //设置当前获得锁的线程
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {
                    //如果 c 不为 0,说明锁被某个线程获得了,能进这里说明获取锁的线程也是当前线程,说明当前线程 lock()了两次,所以是可重入的,此时将 state 增加
                    int nextc = c + acquires;
                    if (nextc < 0)
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                //此时锁被其他线程获得了,则返回 false
                return false;
            }
    
    
    @AbstractQueuedSynchronizer
    //tryAcquire(args) 返回 true 说明获得锁成功,直接跳出去执行方法体
    //tryAcquire(args)返回 false,则会进行 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)
    public final void acquire(int arg) {
            if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
                selfInterrupt();
        }
    
    @AbstractQueuedSynchronizer
    //将当前线程入队
    private Node addWaiter(Node mode) {
            Node node = new Node(Thread.currentThread(), mode);
            // Try the fast path of enq; backup to full enq on failure
            Node pred = tail;
            if (pred != null) {
                node.prev = pred;
                if (compareAndSetTail(pred, node)) {
                    pred.next = node;
                    return node;
                }
            }
            enq(node);
            return node;
        }
    
    @AbstractQueuedSynchronizer
    //进入死循环等待,每次会获取等待队列的第一个线程,执行tryAcquire(arg)尝试去获得锁,如果获得,则将 status 设置为 1,表示获得了锁
     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);
            }
        }
    

    释放锁

    @ReentrantLock
    public void unlock() {
            sync.release(1);
        }
    
    @AbstractQueuedSynchronizer
     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) {
                //将锁的信号量-1
                int c = getState() - releases;
                //获得锁的线程和释放锁的线程不是同一个,抛异常
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                boolean free = false;
                //如果自减后 c==0,则释放锁
                if (c == 0) {
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                //如果当前线程重入了多次,只把 status-1,线程会继续保留锁
                setState(c);
                return free;
            }
    
    
    @AbstractQueuedSynchronizer
     private void unparkSuccessor(Node node) {
           
            int ws = node.waitStatus;
            if (ws < 0)
                compareAndSetWaitStatus(node, ws, 0);
    
             //倒序遍历队伍,找出待唤醒的线程
            Node s = node.next;
            if (s == null || s.waitStatus > 0) {
                s = null;
                for (Node t = tail; t != null && t != node; t = t.prev)
                    if (t.waitStatus <= 0)
                        s = t;
            }
            if (s != null)
                //唤醒线程
                LockSupport.unpark(s.thread);
        }
    

    公平锁和非公平锁关键在于

    @非公平锁,NonfairSync
    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;
            }
    
    @FairSync
    protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    //如果刚好可以获得锁,并且等待队伍为空才获得锁,否则将自己插入等待队伍队尾
                    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;
            }
    

    相关文章

      网友评论

          本文标题:ReentrantLock 解析

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