烟台网站建设找三硕科技微信商城系统

当前位置: 首页 > news >正文

烟台网站建设找三硕科技,微信商城系统,wordpress后台插件的关闭,阿里云主机可以放几个网站一、ReentrantLock ReentrantLock 是 java JUC 中的一个可重入锁#xff0c;在上篇文章讲解 AQS 源码的时候提到 ReentrantLock 锁是基于 AQS 实现的#xff0c;那是如何使用的 AQS 呢#xff0c;本篇文章一起带大家看下 ReentrantLock 的源码。 在 AQS 中#xff0c;如果…一、ReentrantLock ReentrantLock 是 java JUC 中的一个可重入锁在上篇文章讲解 AQS 源码的时候提到 ReentrantLock 锁是基于 AQS 实现的那是如何使用的 AQS 呢本篇文章一起带大家看下 ReentrantLock 的源码。 在 AQS 中如果需要使用AQS的特征则需要子类根据使用的场景重写下面方法 //查询是否正在独占资源condition会使用 boolean isHeldExclusively() //独占模式尝试获取资源成功则返回true失败则返回false boolean tryAcquire(int arg) //独占模式尝试释放资源成功则返回true失败则返回false boolean tryRelease(int arg) //共享模式尝试获取资源如果返回负数表示失败否则表示成功。 int tryAcquireShared(int arg) //共享模式尝试释放资源成功则返回true失败则返回false。 boolean tryReleaseShared(int arg)由于这里 ReentrantLock 锁的特性所以下面我们只需关注独占模式下的几个方法即可。 说明本文中关于 AQS 中的方法没有做过多的解释不了解的小伙伴可以看下这篇对 AQS 源码分析的文章和当前文章在同一专栏 https://blog.csdn.net/qq_43692950/article/details/129367736 下面一起开始 ReentrantLock 源码的分析 二、ReentrantLock 的 Sync、FairSync、NonfairSync 2.1 Sync、FairSync、NonfairSync 在声明 ReentrantLock 锁时有两种方式一种是无参构造函数一种则需要指定一个 fair 参数 new ReentrantLock(); new ReentrantLock(false);当使用无参构造函数声明时则是创建了一个 NonfairSync 对象 通过有参的构造函数则根据传入的 fair 可以选择创建一个 FairSync 对象 其实这里也不难理解 NonfairSync 和 FairSync 其实就是ReentrantLock 锁中的非公平锁和公平锁两种类型。 点到这两个类中可以看到都继承自 Sync 类 而 Sync 类则继承了 AQS 到这里了我们寻找几个关键的方法在AQS中独占模式下两大关键的方法是交由子类进行实现的分别是 tryAcquire 尝试获取资源和 tryRelease 尝试释放资源。 首先来看 tryAcquire 尝试获取资源 通过 Sync 类的实现源码发现并没有重写 tryAcquire 方法那该方法肯定在下面的子类FairSync 和 NonfairSync 分别看下源码确实存在重写的方法 2.2 NonfairSync 下的 tryAcquire 首先看下 NonfairSync 的 tryAcquire 实现逻辑可以看到又调用了 nonfairTryAcquire 就是 Sync 类中的 nonfairTryAcquire 从命名上可以分析出就是非公平锁的尝试获取资源直观就是非公平锁下获取锁操作 进入到 Sync 类中的 nonfairTryAcquire中可以看到首先获取到 AQS 中的共享资源 state如果 state 等于 0 则将 state 的值修改为 acquires默认为1下面会分析到并设置AQS的独占线程为当前线程并返回 true 说白了不就是获取到锁了吗那就可以理解为 state 等于 0 即是无锁的状态下面将 state 的值修改为 acquires 就是获取到锁了改变资源的状态 接着如果 state 的值不是 0 则当前锁已经被别的线程持有了这里又判断了下如果持有锁的线程正好是当前的线程那不就是锁的重入吗这种情况下可以直接获得锁不过这里为了记录重入的次数对 state 共享资源进行了 acquires 操作其实就是 1 操作。 如果都没有成功那此时则获取锁失败返回 false 2.3 FairSync下的 tryAcquire 在 FairSync 类下的 tryAcquire 方法中和前面 NonfairSync 类似但不同的是在获取到锁时也就是拿到 state 等于 0 进行修改资源时多了步 hasQueuedPredecessors 的判断 下面可以进到 hasQueuedPredecessors 的方法中可以看到是由 AQS 提供的方法主要就是判断当前节点线程的前面是否还有等待的线程因为 FairSync 实现的是公平锁的原则如果当前线程前面还有等待线程则获取锁资源也轮不到自个让前面的老大先来 hasQueuedPredecessors 方法理解后其余的逻辑则和 NonfairSync 中的一致了。 2.4 tryRelease 到这里已经了解到了tryAcquire 尝试获取资源的逻辑上面提到了两个重要方法还有一个 tryRelease 没有分析逻辑还是首先看 Sync 类中是否有重写该方法 通过源码可以看到在 Sync 类中就已经对 tryRelease 进行了重写而 NonfairSync 和 FairSync 中都没有重写该方法那释放资源就是走的 Sync 类下的 tryRelease 方法
在该方法中可以看到首先还是获取到了 AQS 中的 state 共享资源然后对该资源进行 - releases 默认releases为1下面会提到 操作其实就是 -1 操作 接着判断了下如果当前线程不是持有锁线程就抛出异常也好理解没有持有锁的线程跑过来释放锁那肯定有问题了呀。 接着再进行判断 state 是不是等于 0 上面讲到在锁重入的情况下记录重入的次数是对 state 进行 1 操作而这边又对 state 进行 -1 操作如果减到最后 state 有成了最初的 0 那不就是重入的锁和当前持有的锁都释放完了吗这个时候就可以将持有锁的线程置为空了并修改最新的 state 看到这里就会发现获取锁和释放锁无非就是对 AQS 中的共享资源进行操作。理解了这两大核心的方法后下面就可以看如何运用在 ReentrantLock 中的了。 三、lock.lock() 在 ReentrantLock 中需要获取锁时直接使用 lock.lock() 即可那 lock.lock() 到底做了什么呢点到该方法中可以看到是调用的 Sync 的 lock 方法而 Sync 中的lock 方法是抽象方法具体实现肯定在子类的 NonfairSync、 FairSync 中。 3.1 NonfairSync.lock() 首先看点 NonfairSync 非公平锁中的 lock 方法直接进行了将 AQS 中的共享资源 state 由 0 改为 1 如果修改成功根据上面分析的结论不就是获取锁成功了吗可以将AQS中的独占线程设为自己了。但是如果其他线程修改成功了这里使用 CAS 就会修改失败因此就会进到 acquire 方法注意这里传递的参数默认就是 1 对应着前面括号中的说明 而 acquire 方法就是 AQS 中的独占模式获取同步资源的逻辑会调用当前方法的 tryAcquire 尝试获取资源如果获取不到则加入到 AQS 的阻塞队列并阻塞挂起线程。 关于acquire 方法的源码解读可以参考文章开始的链接中对 AQS 源码的解读。 3.2 FairSync.lock() 在 FairSync 公平锁中由于需要遵循先进先出的原则这里没有直接已粗暴的形式对 state 进行修改而是直接调用了 AQS 中的 acquire 方法而 acquire 方法又会调用当前类的 tryAcquire 获取资源。 但在当前类的 tryAcquire 方法中如果获取到了资源会接着进行判断当前线程的前面是否还有等待的线程如果有则让出来让别人获取资源因此就遵循了公平锁的原则注意这里传递的参数默认就是 1 同样对应着前面括号中的说明 同样 tryAcquire 尝试获取资源如果获取不到则加入到 AQS 的阻塞队列并阻塞挂起线程。 四、lock.unlock() 上面了解到了 lock 的逻辑既然上锁了肯定需要解锁下面点到 unlock() 方法中可以看到直接使用了 Sync 的 release 方法释放资源其实是 AQS 中的 release 方法注意这里传递的参数默认就是 1 同样对应着前面括号中的说明 在 AQS 的release 方法中首先会调用 Sync 类的 tryRelease 释放资源然后对已阻塞的线程进行唤醒 关于release 方法的源码解读可以参考文章开始的链接中对 AQS 源码的解读。 五、总结 通过阅读 ReentrantLock 的源码可以发现大量依赖于 AQS 中提供的方法所以在阅读前一定要理解下 AQS 的作用和功能。