可重入锁ReetrantLock源码分析

本文详细解析了ReentrantLock中的公平锁和非公平锁实现原理,包括加锁和释放锁的过程,对比了两种锁的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、前言

关于锁,大家都清楚的是synchronized,和lock接口。关于lock显式锁,我们常用的是ReentrantLock类中的公平锁和非公平锁。本篇文章根据ReentrantLock和AbstractQueuedSynchronizer的源码来分析可重入锁中的公平锁和非公平锁的实现机制。

2、非公平锁

在ReentrantLock中默认的是非公平锁,我们先来看一下非公平锁的实现机制。

2.1、加锁

final void lock() {
        	//如果state为0,并且可以利用CAS更新成1,则加锁成功
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
            	//获取锁
                acquire(1);
        }

其中 acquire(1) 的具体实现如下:
调用AbstractQueuedSynchronizer的 acquire 方法

 public final void acquire(int arg) {
 //如果tryAcuqre不成功,则将节点放入同步队列SynQueue中
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

其中tryAcquire()代码入下:

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) {
			//如果设置状态为acquires则表示获取锁成功
                if (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;
        }

2.2、释放锁

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

release 方法的源代码如下:

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

其中 tryRelease源码如下:

protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
			//如果state为0,则表示锁释放成功
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

3、公平锁

3.1、加锁

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

其中 acquire 方法和之前的一样。
代码再贴一下:

 public final void acquire(int arg) {
 //如果tryAcuqre不成功,则将节点放入同步队列SynQueue中
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

其中 tryAcquire 的实现不一样了。如下所示:

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

3.2、释放锁

公平锁和非公平锁的释放公用一套代码。这里就不过多叙述了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值