JUC之ReentrantLock

30 篇文章 0 订阅

JUC之ReentrantLock

一、什么是ReentrantLock

ReentrantLock就是可重入锁,它主要实现了以下两种机制:

  • 可重入,一个线程可以重复获取该锁。
  • 公平性,它实现了公平锁与非公平锁。
    • 前者能够解决饥饿问题,但是会耗费进百倍的性能
    • 后者可能会造成饥饿问题,但是,性能更好。
  • 可重入锁,它本身是一个独占锁。

二、ReentrantLock的实现

1、重入机制的实现

  • 解决重入问题
protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
  //计数为0,无需解决重入问题,直接CAS获取
    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;
}
  • 解决重入释放问题
protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
  //重入N次,知道释放N次,才返回true,否则一直都是false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}

2、公平机制的实现

  • fair
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;
}
  • unfair
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的应用

在java中,基本上所有的锁都是可重入锁,因为可重入锁本身就是为了避免死锁问题,死锁从某种意义上讲是一种错误的行为,为了纠正这种行为,所有的锁都设计成可重入锁。以下是重入锁的一些应用:

  • ReentrantReadWriteLock
    • ReadLock
    • WriteLock
  • CyclicBarrier
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值