前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java多线程---ReentrantLock解析

Java多线程---ReentrantLock解析

作者头像
None_Ling
发布2018-10-23 14:39:51
3330
发布2018-10-23 14:39:51
举报
文章被收录于专栏:Android相关Android相关

Lock函数

ReentrantLock中有两种Sync,一种是NonfairSync另一种是FairSync。它两同时继承Sync类。可以在创建ReentrantLock的时候指定用那种锁。

在FairSync的lock方法中,会调用acquire(1),而acquire方法如下

代码语言:javascript
复制
 /**
 * Acquires in exclusive mode, ignoring interrupts.  Implemented
 * by invoking at least once {@link #tryAcquire},
 * returning on success.  Otherwise the thread is queued, possibly
 * repeatedly blocking and unblocking, invoking {@link
 * #tryAcquire} until success.  This method can be used
 * to implement method {@link Lock#lock}.
 *
 * @param arg the acquire argument.  This value is conveyed to
 *        {@link #tryAcquire} but is otherwise uninterpreted and
 *        can represent anything you like.
 */
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

acquire中会判断:

  1. !tryAcquire(arg):尝试去获取锁,但是获取失败
  2. acquireQueued(addWaiter(Node.EXCLUSIVE),arg):创建一个新的Node并且添加到链表尾部,再调用acquireQueued方法,判断该节点是否在waiting的状态,需要被interrupt。 如果满足的话,则会调用selfInterrupt,其中会调用Thread.currentThread().interrupt(),进行当前线程的中断操作

而在FairSync中重写了tryAcquire方法

代码语言:javascript
复制
 /**
     * 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 (!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;
    }
}

在这个方法中:

  1. 首先获取当前尝试加锁的线程
  2. 获取当前锁的状态
  3. 判断当前是否有被加锁,如果没有的话,那么则判断队列中是否已经有等待的了,如果没有等待的话,再通过CAS操作赋值acquires,如果满足的话,那么调用setExclusiveOwnerThread,将持有锁的线程设置为当前线程
  4. 如果当前state不为0,也就是锁已经存在了的话,那么则判断尝试获取锁的线程是否为当前线程,如果为当前线程的话,那么则再将锁+1,然后设置锁状态返回true
  5. 否则返回false

在hasQueuedPredecessors函数中,会判断,如果头尾节点不相同,并且头节点的后继为空或者头节点的后继中线程不是当前线程,就说明等待队列不为空。

如果等待队列为空的话,那么就通过CAS操作设置state,如果设置成功的话,那么就将当前线程设置成持有锁的线程,并且返回true,说明已经成功获取锁了。

否则,如果state不为0的话,那么则判断当前线程是不是就是已经持有锁的线程,如果是的话,那么就把当前状态+请求的值(1),然后设置当前的State值,饭后返回true,说明获取锁成功。否则,返回false,说明获取锁失败。

只有当获取锁失败,并且成功添加到链表尾部,才会被中断。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.05.30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Lock函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档