JavaSE(22)——ReentrantLock源码

ReentrantLock源码

1. 源码注释

  1. 跟synchronized具有相同的功能和语义(都是互斥锁),但它具有更好的拓展性。

  2. 通过这两个方法判断当前线程是否拥有锁

    isHeldByCurrentThread

    getHoldCount

  3. 构造方法支持使用参数来让锁设计为公平锁,公平锁一般的吞吐量会低一些,但一定程度保住了“相对公平”

  4. 不计时 tryLock()方法不符合公平锁的设定

  5. 在try代码块之前调用lock,这是最应该使用的方式

  6. Lock接口还定义了一些监听锁状态的方法

  7. 一个被序列化的锁是处于不锁定状态的

2. 分析

2.1 内部类

ReentrantLock有三个内部类

  1. 继承了AQS的Sync
    1. Sync的子类NonfairSync
    2. Sync的子类FairSync。

通过子类可以看到,ReentrantLock是支持公平锁和非公平锁的

2.2 构造方法

//无参构造方法,默认使用非公平锁
public ReentrantLock() {
    sync = new NonfairSync();
}

//通过制定参数,可以初始化公平锁或非公平锁
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

2.3 Lock方法

  • 公平锁

    public void lock() {
        sync.lock();
    }
    
    //FairSync中的lock方法
    final void lock() {
        acquire(1);
    }
    
    //AQS中的方法
    public final void acquire(int arg) {
        //尝试获取锁,成功则返回true,则当前方法结束
        if (!tryAcquire(arg) &&
            //当前锁被其他线程持有,准备入等待队列
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            
            selfInterrupt();
    }
    
    //FairSync中的方法,尝试获取锁
    protected final boolean tryAcquire(int acquires) {
        //获取当前线程
        final Thread current = Thread.currentThread();
        //获取锁状态
        int c = getState();
        
      	//C == 0,则当前无锁
        if (c == 0) {
            //队列未初始化,hasQP方法返回false
            if (!hasQueuedPredecessors() &&
                //将state值设为1
                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;
    }
    
    //AQS中的判断方法
    //无锁时,当前队列中没有元素,则返回false
    //有锁时,当前队列
    public final boolean hasQueuedPredecessors() {
    
        Node t = tail; // Read fields in reverse initialization order
        Node h = head;
        Node s;
        return h != t &&
            ((s = h.next) == null || s.thread != Thread.currentThread());
    }
    
    //创建等待队列中的结点
    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;
    }
    
    
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            //再次确认队尾为空,需要初始化队列
            if (t == null) {
                //将空节点设置为队列的头
                if (compareAndSetHead(new Node()))
                    //将队尾设置为该空节点
                    tail = head;
            } 
            //队列不为空
            else {
                //将新节点放在空结点之后
                node.prev = t;
                //将新节点设置插入到队尾
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    //返回队尾
                    return t;
                }
            }
        }
    }
    
    //尝试让队列中的线程获取锁
    //node:刚插入队列的新节点
    //arg: 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;
                }
                //获取锁失败,或者当前节点不是队列中有机会获取锁的结点
                //判断当前节点是否应该被park
                //true则将当前节点park
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
            
        } finally {
            //当插入尝试时,成功获取锁,则将队列中的结点设置为取消状态
            if (failed)
                cancelAcquire(node);
        }
    }
    
    //取消获取锁的状态
    private void cancelAcquire(Node node) {
        // Ignore if node doesn't exist
        if (node == null)
            return;
    
        node.thread = null;
    
        Node pred = node.prev;
        while (pred.waitStatus > 0)
            node.prev = pred = pred.prev;
    
        Node predNext = pred.next;
    
        //当前节点的状态设置为取消
        node.waitStatus = Node.CANCELLED;
    
        //如果当前节点为队尾,就把空节点放到队尾,且将它头尾相连
        if (node == tail && compareAndSetTail(node, pred)) {
            compareAndSetNext(pred, predNext, null);
        } else {
            int ws;
            if (pred != head &&
                ((ws = pred.waitStatus) == Node.SIGNAL ||
                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                pred.thread != null) {
                Node next = node.next;
                if (next != null && next.waitStatus <= 0)
                    compareAndSetNext(pred, predNext, next);
            } else {
                unparkSuccessor(node);
            }
    
            node.next = node; // help GC
        }
    }
    
  • 非公平锁

    //非公平锁的lock方法
    final void lock() {
        //一进来先进行CAS抢占锁
        if (compareAndSetState(0, 1))
            //抢占成功则设置当前线程为锁的持有线程
            setExclusiveOwnerThread(Thread.currentThread());
        else
            //失败则尝试获取锁
            acquire(1);
    }
    
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
    
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
    
    final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            //非公平锁的特别之处,在请求锁时,当锁可以被获取时,直接进行CAS抢占。
            //抢占失败,则进行正常排队流程,不再抢占
            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;
    }
    
    
    

2.4 unlock方法

public void unlock() {
    sync.release(1);
}

//
//arg:1
public final boolean release(int arg) {
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

//
//releases:1
protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    //如果当前解锁线程不等于正在持有锁的线程,则抛出异常
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    
    boolean free = false;
    //如果释放后处于无锁状态,则将当前锁持有者设为空
    //如果释放后不等于0,当前存在重入,则将重入锁状态-1,
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}

//唤醒后继节点
private void unparkSuccessor(Node node) {
   
    int ws = node.waitStatus;
    if (ws < 0)
        //将节点status设为0,代表当前节点正在持有锁
        compareAndSetWaitStatus(node, ws, 0);

    Node s = node.next;
   
    if (s == null || s.waitStatus > 0) {
        //如果后续节点为空,或者status为cancel,设置该节点为null
        s = null;
        //从尾部遍历,寻找临近s的等待状态有效的节点
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0)
                s = t;
    }
    //如果后继节点有效
    if (s != null)
        //唤醒该线程
        LockSupport.unpark(s.thread);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值