深入理解ReentrantLock/ReentrantReadWriteLock

ReentrantLock(可重入锁)

ReentrantLock获取锁和释放锁可以参考这篇博客:https://blog.csdn.net/sophia__yu/article/details/84313234
一:ReentrantLock如何实现可重入

ReentrantLock实现Lock接口的可重入子类。可重入的意思就是一个线程在获取锁的时候,如果该线程已经获取到锁则直接获取成功,不会被阻塞;
由于会获取n次锁,那么在锁释放的时候也需要释放n次,才能完全释放成功。

可重入锁是在tryAcquire()阶段实现的:
源码如下:

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()) {
   
            //如果是,再次获取将状态+1,实现可重入
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

如果该同步状态不为0,表示此时同步状态已被线程获取,再判断同步状态的线程是否是当前线程,如果是,同步状态再次加1,并返回true,表示持有线程重入同步块。

可重入锁释放
源码如下:

protected final boolean tryRelease(int releases) {
   
//释放锁第一步,将同步状态-1
            int c = getState() - releases;
            //如果持有锁线程不是当前线程直接抛异常
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            //如果同步状态为0,才将当前持有锁线程置空
            if (c == 0) {
   
                free = true;
                setExclusiveOwnerThread(null);
            }
            //如果同步状态不为0,更新同步状态,锁没有完全释放
            setState(c);
            return free;
        }

当且仅当同步状态减为0并且持有线程为当前线程时表示正确释放。
否则调用setState()将-1后的状态进行更新。

二:公平锁与非公平锁

synchronized可以实现重入,但是synchronized只能实现非公平锁,而
ReentrantLock即可以实现公平锁也可以实现非公平锁。 那什么是公平锁和非公平锁呢?
如果线程获取锁的顺序与请求等待时间保持一致,满足FIFO,那么这个锁是公平的,否则为非公平锁。
看一系列ReentrantLock源码:

 public ReentrantLock() {
   
 		//非公平锁
        sync = new NonfairSync();
    }

可以看到ReentrantLock锁默认是非公平锁,但是有一个重载方法实现公平机制:

public ReentrantLock(boolean fair) {
   
//如果fair是true,是实现公平,否则非公平锁
        sync = fair ? new FairSync() : new NonfairSync();
    }

要使用公平锁,调用ReentrantLock有参构造传入true,获取内置的公平锁。

非公平锁与公平锁实现区别:
非公平锁:

static final class NonfairSync extends Sync {
   
        final void lock() {
   
        //首先先CAS,新启动线程很有可能不入队,直接获取同步状态,那么队头线程依然在等待
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

/再次尝试获取锁
final boolean nonfairTryAcquire(int acquires) {
   
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
   
            //如果同步状态为0,直接CAS,那么新的线程可能会抢占已经排队的线程的锁的使用权,也就是队头线程依然在等待
                if (compareAndSetState(0, acquires)) {
   
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else i
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值