ReentrantReadWriteLock

本文详细解析了ReentrantReadWriteLock的内部实现机制,包括读锁和写锁的获取与释放过程,通过分析AQS框架下的自定义同步器,阐述了读写锁的公平性和非公平性策略。

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

一、同步器

先来看看读写锁持有的同步器,实现了AQS;读锁和写锁持有同一个Sync
abstract static class Sync extends AbstractQueuedSynchronizer

        static final int SHARED_SHIFT   = 16;//偏移量
        //读锁的基础数,读锁数放在高16位
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;//获取锁的最大数量
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;//独占
        //利用位运算将读锁状态放在低16位,读锁状态放在高16位
        //读锁数量
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
        //写锁数量
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }


一、读锁

ReentrantReadWriteLock.ReadLock是ReentrantReadWriteLock的一个静态内部类;


    public void lock() {
            sync.acquireShared(1);
        }
 
    public final void acquireShared(int arg) {
        //尝试获取锁
        if (tryAcquireShared(arg) < 0)
            //获取锁失败后的操作  
            doAcquireShared(arg);
    }
1、tryAcquireShared(int)
    //读锁自定义的尝试获取锁的方法
    protected final int tryAcquireShared(int unused) {
            /*
             * Walkthrough:
             * 1. If write lock held by another thread, fail.
             * 2. Otherwise, this thread is eligible for
             *    lock wrt state, so ask if it should block
             *    because of queue policy. If not, try
             *    to grant by CASing state and updating count.
             *    Note that step does not check for reentrant
             *    acquires, which is postponed to full version
             *    to avoid having to check hold count in
             *    the more typical non-reentrant case.
             * 3. If step 2 fails either because thread
             *    apparently not eligible or CAS fails or count
             *    saturated, chain to version with full retry loop.
             */
            Thread current = Thread.currentThread();
            int c = getState();
            // 获取写锁数量判断是否存在写锁,和写锁的线程是否是当前线程
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;
            int r = sharedCount(c);
            // 读是否需要加锁
            if (!readerShouldBlock() &&
                r < MAX_COUNT &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                //获取锁成功
                if (r == 0) {
                    //第一个获取读锁
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    //当前线程再次获取读锁
                    firstReaderHoldCount++;
                } else {
                    //缓存最后一个获取读锁的线程 获取锁个数的计数器
                    HoldCounter rh = cachedHoldCounter;
                    // null或者不是当前线程的计数器
                    if (rh == null || rh.tid != getThreadId(current))
                        //从ThreadLocal中获取或者初始化
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                }
                return 1;
            }
            return fullTryAcquireShared(current);
        }

判断读锁是否应该被阻塞方法readerShouldBlock()

    //非公平锁的实现
    final boolean readerShouldBlock() {
            return apparentlyFirstQueuedIsExclusive();
        }
    // 如果队列不为空 显然在队列的头部是排他锁;且第二节点不为空且不是共享锁并且不是      //当前线程持有,则读锁无法获取
    final boolean apparentlyFirstQueuedIsExclusive() {
        Node h, s;
        return (h = head) != null &&
            (s = h.next)  != null &&
            !s.isShared()         &&
            s.thread != null;
    }
    
    /******公平锁的实现***********/
    final boolean readerShouldBlock() {
            return hasQueuedPredecessors();
        }
        
    public final boolean hasQueuedPredecessors() {
        // 头不等于尾,表示队列至少有2个节点
        // 第二节点为null,或者不是当前线程持有
        //如果第二节点是当前线程持有,head就是写锁,那么可以尝试获取锁
        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());
    }

上一步获取失败

    
    //完整版获取共享锁
    final int fullTryAcquireShared(Thread current) {
            /*
             * This code is in part redundant with that in
             * tryAcquireShared but is simpler overall by not
             * complicating tryAcquireShared with interactions between
             * retries and lazily reading hold counts.
             */
            HoldCounter rh = null;
            // 自旋获取,除非出现获取失败,或者成功;就会一直自旋 知道出现前面两种情况
            for (;;) {
                int c = getState();
                //判断是否获取写锁并且不是当前线程获取(返回-1表示获取失败)
                if (exclusiveCount(c) != 0) {
                    if (getExclusiveOwnerThread() != current)
                        return -1;
                    // else we hold the exclusive lock; blocking here
                    // would cause deadlock.
                } else if (readerShouldBlock()) {
                    // 确保我们没有重新获取锁
                    if (firstReader == current) {
                        // assert firstReaderHoldCount > 0;
                    } else {
                        if (rh == null) {
                            rh = cachedHoldCounter;
                            if (rh == null || rh.tid != getThreadId(current)) {
                                rh = readHolds.get();
                                if (rh.count == 0)
                                    readHolds.remove();
                            }
                        }
                        if (rh.count == 0)
                            return -1;
                    }
                }
                if (sharedCount(c) == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                if (compareAndSetState(c, c + SHARED_UNIT)) {
                    if (sharedCount(c) == 0) {
                        firstReader = current;
                        firstReaderHoldCount = 1;
                    } else if (firstReader == current) {
                        firstReaderHoldCount++;
                    } else {
                        if (rh == null)
                            rh = cachedHoldCounter;
                        if (rh == null || rh.tid != getThreadId(current))
                            rh = readHolds.get();
                        else if (rh.count == 0)
                            readHolds.set(rh);
                        rh.count++;
                        cachedHoldCounter = rh; // cache for release
                    }
                    return 1;
                }
            }
        }
2、doAcquireShared(int)

查看AQS 共享锁部分AQS源码解析

3、releaseShared(int)

public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            //唤醒下个节点
            doReleaseShared();
            return true;
        }
        return false;
    }

    protected final boolean tryReleaseShared(int unused) {
            Thread current = Thread.currentThread();
            if (firstReader == current) {
                // assert firstReaderHoldCount > 0;
                if (firstReaderHoldCount == 1)
                    firstReader = null;
                else
                    firstReaderHoldCount--;
            } else {
                HoldCounter rh = cachedHoldCounter;
                //从ThreadLocal中获取计数器
                if (rh == null || rh.tid != getThreadId(current))
                    rh = readHolds.get();
                int count = rh.count;
                if (count <= 1) {
                    readHolds.remove();
                    if (count <= 0)
                        throw unmatchedUnlockException();
                }
                --rh.count;
            }
            for (;;) {
                int c = getState();
                int nextc = c - SHARED_UNIT;
                if (compareAndSetState(c, nextc))
                    // Releasing the read lock has no effect on readers,
                    // but it may allow waiting writers to proceed if
                    // both read and write locks are now free.
                    return nextc == 0;
            }
        }

二、写锁

主要实现了AQS的tryAcquire方法

    protected final boolean tryAcquire(int acquires) {
           
            Thread current = Thread.currentThread();
            int c = getState();
            int w = exclusiveCount(c);
            if (c != 0) {// 表示已经有锁被获取了
                // (Note: if c != 0 and w == 0 then shared count != 0)
                if (w == 0 || current != getExclusiveOwnerThread())
                   //读写互斥 获取失败
                   return false;
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                // 锁已被自己获取,重入
                setState(c + acquires);
                return true;
            }
            //非公平锁永远false,非公平必须按队列顺序,所以需要判断队列是否为空,或者第二节点是否是当前线程持有,才有资格尝试获取锁
            if (writerShouldBlock() ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }

我们来看看公平锁的writeShouldBlock


    final boolean writerShouldBlock() {
            return hasQueuedPredecessors();
        }
        
    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());
    }
内容概要:本文档详细介绍了基于MATLAB实现的无人机三维路径规划项目,核心算法采用蒙特卡罗树搜索(MCTS)。项目旨在解决无人机在复杂三维环境中自主路径规划的问题,通过MCTS的随机模拟与渐进式搜索机制,实现高效、智能化的路径规划。项目不仅考虑静态环境建模,还集成了障碍物检测与避障机制,确保无人机飞行的安全性和效率。文档涵盖了从环境准备、数据处理、算法设计与实现、模型训练与预测、性能评估到GUI界面设计的完整流程,并提供了详细的代码示例。此外,项目采用模块化设计,支持多无人机协同路径规划、动态环境实时路径重规划等未来改进方向。 适合人群:具备一定编程基础,特别是熟悉MATLAB和无人机技术的研发人员;从事无人机路径规划、智能导航系统开发的工程师;对MCTS算法感兴趣的算法研究人员。 使用场景及目标:①理解MCTS算法在三维路径规划中的应用;②掌握基于MATLAB的无人机路径规划项目开发全流程;③学习如何通过MCTS算法优化无人机在复杂环境中的飞行路径,提高飞行安全性和效率;④为后续多无人机协同规划、动态环境实时调整等高级应用打下基础。 其他说明:项目不仅提供了详细的理论解释和技术实现,还特别关注了实际应用中的挑战和解决方案。例如,通过多阶段优化与迭代增强机制提升路径质量,结合环境建模与障碍物感知保障路径安全,利用GPU加速推理提升计算效率等。此外,项目还强调了代码模块化与调试便利性,便于后续功能扩展和性能优化。项目未来改进方向包括引入深度强化学习辅助路径规划、扩展至多无人机协同路径规划、增强动态环境实时路径重规划能力等,展示了广阔的应用前景和发展潜力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值