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

了解ReentrantLock

作者头像
崔笑颜
发布2020-06-08 16:58:27
4920
发布2020-06-08 16:58:27
举报
文章被收录于专栏:小小码农一个。

ReetrantLock是一个可重入的独占锁,主要有两个特性,一个是支持公平锁和非公平锁,一个是可重入。 ReetrantLock实现依赖于AQS(AbstractQueuedSynchronizer) ReetrantLock主要依靠AQS维护一个阻塞队列,多个线程对加锁时,失败则会进入阻塞队列。等待唤醒,重新尝试加锁。下图是其类图

20180226134553506-45bd7b55ef6b42dc9cc3d958d720a1e7
20180226134553506-45bd7b55ef6b42dc9cc3d958d720a1e7

支持公平锁和非公平锁

  1. 公平锁:多个线程申请获取同一资源时,必须按照申请顺序,依次获取资源。
  2. 非公平锁:资源释放时,任何线程都有机会获得资源,而不管其申请顺序。 具体原理分析

在new ReetrantLock对象的时候,可以指定其支持公平锁还是非公平锁

代码语言:javascript
复制
public ReentrantLock() {
	sync = new NonfairSync();
}


public ReentrantLock(boolean fair) {
	sync = fair ? new FairSync() : new NonfairSync();
}

公平锁原理

FairSync继承Sync,而Sync继承AbstractQueuedSynchronizer。ReentrantLock调用lock方法,最终会调用sync的tryAcquire函数,获取资源。FairSync的tryAcquire函数,**当前线程只有在队列为空或者时队首节点的时候,才能获取资源,否则会被加入到阻塞队列中。**下面的hasQueuedPredecessors函数用于判断队列是否为空,或者当前元素是否为队首元素。

代码语言:javascript
复制
static final class FairSync extends Sync {
    private static final long serialVersionUID = -3000897897090466540L;

    final void lock() {
        acquire(1);
    }

    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;
    }
}

hasQueuedPredecessors函数,如果h==t(队列为空),或者h!=t && s.thread == Thread.currentThread()(队首节点),则返回false,否则返回true

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

非公平锁原理

NoFairSync同样继承Sync,ReentrantLock调用lock方法,最终会调用sync的tryAcquire函数,获取资源。而NoFairSync的tryAcquire函数,会调用父类Sync的方法nofairTryAcquire函数。通过对比可以发现,如果资源释放时,新的线程会尝试CAS操作获取资源,而不管阻塞队列中时候有先于其申请的线程。

代码语言:javascript
复制
static final class NonfairSync extends Sync {
    private static final long serialVersionUID = 7316153563782823691L;
    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }

    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
}
代码语言:javascript
复制
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;
}

可重入性

可重入性:获取独占资源的线程,可以重复得获取该独占资源,不需要重复请求。

请求独占资源时,可重入性的体现

ReentrantLock在申请资源的时候,都会判断当前持有独占资源的线程是不是当前线程,如果是的话,只是简单得将state值加1.记录当前线程的重入次数。

代码语言:javascript
复制
 else if (current == getExclusiveOwnerThread()) {
     int nextc = c + acquires;
     if (nextc < 0)
     	throw new Error("Maximum lock count exceeded");
     setState(nextc);
     return true;
 }

释放资源时,可重入性的体现

ReentrantLock在释放资源的时候,都会调用tryRelease,只有state值为0的时候,才会释放资源。换句话说就是,重入多少次,就必须释放多少次

代码语言:javascript
复制
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;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-04-07,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 支持公平锁和非公平锁
  • 公平锁原理
  • 非公平锁原理
  • 可重入性
    • 请求独占资源时,可重入性的体现
    • 释放资源时,可重入性的体现
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档