死磕源码系列(ReentrantLock)

本文深入剖析了ReentrantLock的工作原理,重点介绍了其基于AbstractQueuedSynchronizer的实现细节,包括state和node的作用,以及如何通过CAS实现线程间的同步。文章详细解释了ReentrantLock如何处理高并发场景下的锁竞争,以及公平锁与非公平锁的区别。

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

前言

  • 在高并发领域,ReentrantLock有着广泛的用处,防止多线程带来的并发问题
  • 对于源码,很多人和我一开始一样都觉得非常神秘
  • 这次我将对ReentrantLock进行全方面的揭秘

核心

  • AbstractQueuedSynchronizer
    • AQS是JDK实现的CAS同步器。里面的核心是state和两个node
    • state标识同步器现在的状态,node作为队列串联同步器中的节点
    • 使用volatile保证参数的可见性
volatile Node prev;
volatile Node next;
private volatile int state;

整体结构

  • ReentrantLock 调用内部类Sync,Sync继承AbstractQueuedSynchronizer

整体流程

  • ReentrantLock调用内部类Sync的acquire方法,底层走的是AbstractQueuedSynchronizer,AbstractQueuedSynchronizer会尝试获取锁,获取失败之后会加入队列中,然后节点自旋去获取锁,一旦成功就将自己的节点至于头部,然后退出。
  • cas实现(compareAndSet)。jdk9之前使用的是unsafe,jsk9之后使用的是varHandler。

核心代码

AQS:

public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
  • tryAcquire是第一次尝试获取所,公平锁和非公平锁的区别只是判断自己节点是否除了head节点外还是在自己前面的,校验的是公平锁,不校验的是非公平锁
  • addWaiter是节点加入到队列中
  • acquireQueued里面执行的就是自旋操作
  final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            //自旋开始
            for (;;) {
                final Node p = node.predecessor();
                //尝试开始获取锁
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

释放锁

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

转载于:https://my.oschina.net/u/3159571/blog/3003157

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值