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

会计公司网站样式网站远程数据库

会计公司网站样式,网站远程数据库,襄阳seo营销,创业谷网站建设规划文章目录 3.深入理解AQS、ReentrantLock3.1AQS3.1.1AQS简介3.1.2核心结构#xff08;1#xff09;设计模型#xff08;2#xff09;组成部分#xff08;3#xff09;State关键字 3.1.3实现的两类队列#xff08;1#xff09;同步队列①CLH②Node③主要行为 img条件队列… 文章目录 3.深入理解AQS、ReentrantLock3.1AQS3.1.1AQS简介3.1.2核心结构1设计模型2组成部分3State关键字 3.1.3实现的两类队列1同步队列①CLH②Node③主要行为 img条件队列 3.1.4总结 3.2ReentrantLock3.2.1Synchronized和ReentrantLock1性能上的比较2获取公平锁3综述 3.2.2可重入功能的实现原理3.2.3非公平锁的实现原理1加锁2释放锁 3.2.4公平锁的实现原理3.2.4tryLock原理3.2.5可中断的获取锁3.2.6可超时的获取锁 3.2.7小结 3.深入理解AQS、ReentrantLock 3.1AQS 3.1.1AQS简介 AQS即队列同步器AbstractQueuedSynchronizer后面简称AQS是实现锁和有关同步器的一个基础框架。 在JDK5中Doug Lea在并发包中加入了大量的同步工具例如重入锁ReentrantLock、读写锁ReentrantReadWriteLock、信号量Semaphore、CountDownLatch倒计时锁等都是基于AQS的。 其内部通过一个被标识为volatile的名为state的变量来控制多个线程之间的同步状态。多个线程之间可以通过AQS来独占式或共享式的抢占资源。 基于AQS可以很方便的实现Java中不具备的功能。 例如在锁这个问题上Java中提供的是synchronized关键字用这个关键字可以很方便的实现多个线程之间的同步。但这个关键字也有很多缺陷比如 不支持超时的获取锁一个线程一旦没有从synchronized上获取锁就会卡在这里没有机会逃脱。所以通常由synchronized造成的死锁是无解的。不可响应中断。不能尝试获取锁。如果尝试获取时没获取到立刻返回synchronized不具备这一特性。 而ReentrantLock基于AQS将上述几点都做到了。 3.1.2核心结构 从AbstractQueuedSynchronizer的名字可以看出AQS中一定是基于队列实现的Queue。 在AQS内部是通过链表实现的队列。 链表的每个元素是其内部类Node的一个实现。然后AQS通过实例变量head指向队列的头通过实例变量tail指向队列的尾。 其源码定义如下 /*** Head of the wait queue, lazily initialized. Except for* initialization, it is modified only via method setHead. Note:* If head exists, its waitStatus is guaranteed not to be* CANCELLED.*/ private transient volatile Node head;/*** Tail of the wait queue, lazily initialized. Modified only via* method enq to add new wait node.*/ private transient volatile Node tail;/*** The synchronization state.*/ private volatile int state;static final class Node {/** 标识为共享式 */static final Node SHARED new Node();/** 标识为独占式 */static final Node EXCLUSIVE null;/** 同步队列中等待的线程等待超时或被中断需要从等待队列中取消等待进入该状态的节点状态将不再变化 */static final int CANCELLED 1;/** 当前节点的后继节点处于等待状态且当前节点释放了同步状态需要通过unpark唤醒后继节点让其继续运行 */static final int SIGNAL -1;/** 当前节点等待在某一Condition上当其他线程调用这个Conditino的signal方法后该节点将从等待队列恢复到同步队列中使其有机会获取同步状态 */static final int CONDITION -2;/** 表示下一次共享式同步状态获取状态将无条件的传播下去 */static final int PROPAGATE -3;/* 当前节点的等待状态取值为上述几个常量之一另外值为0表示初始状态 */volatile int waitStatus;/* 前驱节点 */volatile Node prev;/* 后继节点 */volatile Node next;/* 等待获取同步状态的线程 */volatile Thread thread;/* 等待队列中的后继节点 */Node nextWaiter;// ... }1设计模型 2组成部分 AQS 主要由三部分组成 state 同步状态Node 组成的 CLH 队列ConditionObject 条件变量包含 Node 组成的条件单向队列。 state 用 volatile 来修饰保证了我们操作的可见性所以任何线程通过 getState() 获得状态都是可以得到最新值但是 setState() 无法保证原子性因此 AQS 给我们提供了 compareAndSetState 方法利用底层 UnSafe 的 CAS 功能来实现原子性。 3State关键字 对于 AQS 来说线程同步的关键是对 state 的操作可以说获取、释放资源是否成功都是由 state 决定的比如 state0 代表可获取资源否则无法获取所以 state 的具体语义由实现者去定义现有的 ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch 定义的 state 语义都不一样。 ReentrantLock 的 state 用来表示是否有锁资源变量记录了锁的重入次数ReentrantReadWriteLock 的 state 高 16 位代表读锁状态低 16 位代表写锁状态Semaphore 的 state 用来表示可用信号的个数CountDownLatch 的 state 用来表示计数器的值 3.1.3实现的两类队列 同步队列服务于线程阻塞等待获取资源条件队列服务于线程因某个条件不满足而进入等待状态。 条件队列中的线程实际上已经获取到了资源但是没有能够继续执行下去的条件所以被打入条件队列并释放持有的资源以让渡其它线程执行如果未来某个时刻条件得以满足则该线程会被从条件队列转移到同步队列继续参与竞争资源以继续向下执行。 1同步队列 ①CLH 同步队列是基于链表实现的双向队列也是 CLH 锁的变种。CLH 锁是 AQS 队列同步器实现的基础。 以下图为CLH的构成 CLH 锁是有由 Craig, Landin, and Hagersten 这三个人发明的锁取了三个人名字的首字母所以叫 CLH Lock。CLH 锁是一个自旋锁。能确保无饥饿性。提供先来先服务的公平性。CLH 队列锁也是一种基于链表的可扩展、高性能、公平的自旋锁申请线程仅仅在本地变量上自旋它不断轮询前驱的状态假设发现前驱释放了锁就结束自旋。 ②Node AQS 以内部类 Node 的形式定义了同步队列结点。这就是前文看到的第一个内部类。 static final class Node {/** 模式定义 */static final Node SHARED new Node();static final Node EXCLUSIVE null;/** 线程状态 */static final int CANCELLED 1;static final int SIGNAL -1;static final int CONDITION -2;static final int PROPAGATE -3;/** 线程等待状态 */volatile int waitStatus;/** 前驱结点 */volatile Node prev;/** 后置结点 */volatile Node next;/** 持有的线程对象 */volatile Thread thread;/** 对于独占模式而言指向下一个处于 CONDITION 等待状态的结点对于共享模式而言则为 SHARED 结点 */Node nextWaiter;// ... 省略方法定义 }Node 在 CLH 的基础上进行了变种。 CLH 是单向队列其主要特点是自旋检查前驱节点的 locked 状态。 而 AQS 同步队列是 双向队列每个节点也有状态 waitStatus而其并不是一直对前驱节点的状态自旋判断而是自旋一段时间后阻塞让出 cpu 时间片上下文切换等待前驱节点主动唤醒后继节点。 waitStatus 有如下 5 中状态 CANCELLED 1 表示当前结点已取消调度。当超时或被中断响应中断的情况下会触发变更为此状态进入该状态后的结点将不会再变化。SIGNAL -1 表示后继结点在等待当前结点唤醒。后继结点入队时会将前继结点的状态更新为 SIGNAL。CONDITION -2 表示结点等待在 Condition 上当其他线程调用了 Condition 的 signal() 方法后CONDITION 状态的结点将从等待队列转移到同步队列中等待获取同步锁。PROPAGATE -3 共享模式下前继结点不仅会唤醒其后继结点同时也可能会唤醒后继的后继结点。INITIAL 0 新结点入队时的默认状态。 从上面的代码中可以看出位于 CLH 链表中的线程以 2 种模式在等待资源即 SHARED 和 EXCLUSIVE其中 SHARED 表示共享模式而 EXCLUSIVE 表示独占模式。 共享模式与独占模式的主要区别在于同一时刻独占模式只能有一个线程获取到资源而共享模式在同一时刻可以有多个线程获取到资源。典型的场景就是读写锁读操作可以有多个线程同时获取到读锁资源而写操作同一时刻只能有一个线程获取到写锁资源其它线程在尝试获取资源时都会被阻塞。 ③主要行为 AQS 类成员变量 head 和 tail 字段分别指向同步队列的头结点和尾结点 /*** Head of the wait queue, lazily initialized. Except for* initialization, it is modified only via method setHead. Note:* If head exists, its waitStatus is guaranteed not to be* CANCELLED.*/private transient volatile Node head;/*** Tail of the wait queue, lazily initialized. Modified only via* method enq to add new wait node.*/private transient volatile Node tail;其中 head 表示同步队列的头结点而 tail 则表示同步队列的尾结点具体组织形式如下图 当调用 AQS 的 acquire 方法获取资源时如果资源不足则当前线程会被封装成 Node 结点添加到同步队列的末端入队头结点 head 用于记录当前正在持有资源的线程结点而 head 的后继结点就是下一个将要被调度的线程结点当 release 方法被调用时该结点上的线程将被唤醒出队继续获取资源。 同步队列的主要行为是 入队、出队 入队 获取资源失败的线程需要封装成 Node 节点接着尾部入队在 AQS 中提供 addWaiter 函数完成 Node 节点的创建与入队。添加节点的时候如 CLH 队列已经存在通过 CAS 快速将当前节点添加到队列尾部如果添加失败或队列不存在则初始化同步队列。 /*** Creates and enqueues node for current thread and given mode.** param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared* return the new node*/ private Node addWaiter(Node mode) {Node node new Node(mode);for (;;) {Node oldTail tail;if (oldTail ! null) {node.setPrevRelaxed(oldTail);if (compareAndSetTail(oldTail, node)) {oldTail.next node;return node;}} else {initializeSyncQueue();}} }总结线程获取锁失败入队列将新节点加到 tail 后面然后对 tail 进行 CAS 操作将 tail 指针后移到新节点上。 出队 CLH 队列中的节点都是获取资源失败的线程节点当持有资源的线程释放资源时会将 head.next 指向的线程节点唤醒CLH 队列的第二个节点如果唤醒的线程节点获取资源成功线程节点清空信息设置为头部节点新哨兵节点原头部节点出队原哨兵节点 protected final boolean tryRelease(int releases) {int c getState() - releases; if (Thread.currentThread() ! getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free false;if (c 0) { // 如果 state0 了就是可以释放锁了free true; setExclusiveOwnerThread(null); // 将拿锁线程置为 null}setState(c); // 重置同步器的 statereturn free; // 返回是否成功释放}private void unparkSuccessor(Node node) {// node 节点是当前释放锁的节点也是同步队列的头节点int ws node.waitStatus;// 如果节点已经被取消了把节点的状态置为初始化if (ws 0)compareAndSetWaitStatus(node, ws, 0);// 拿出队二 sNode s node.next;// s 为空表示 node 的后一个节点为空// s.waitStatus 大于 0代表 s 节点已经被取消了// 遇到以上这两种情况就从队尾开始向前遍历找到第一个 waitStatus 字段不是被取消的if (s null || s.waitStatus 0) {s null;// 结束条件是前置节点就是 head 了for (Node t tail; t ! null t ! node; t t.prev)// t.waitStatus 0 说明 t 当前没有被取消肯定还在等待被唤醒if (t.waitStatus 0)s t;}// 唤醒以上代码找到的线程if (s ! null)LockSupport.unpark(s.thread); }总结出队列锁释放唤醒 head 的后继节点head 的后继节点从阻塞中醒来开始抢锁获取锁成功此时 head 指针向后移一个位置原先 head 的后继节点成为新的 head。 2)条件队列 一个 AQS 可以对应多个条件变量 ConditionObject 内部维护着一个单向条件队列不同于 CLH 队列条件队列只入队执行 await 的线程节点并且加入条件队列的节点不能在 CLH 队列 条件队列出队的节点会入队到 CLH 队列。 当某个线程执行了 ConditionObject 的 await 函数阻塞当前线程线程会被封装成 Node 节点添加到条件队列的末端其他线程执行 ConditionObject 的 signal 函数会将条件队列头部线程节点转移到 CLH 队列参与竞争资源具体流程如下图 一个 Condition 对象就有一个单项的等待任务队列。在一个多线程任务中我们可以 new 出多个等待任务队列。比如我们 new 出来两个等待队列。 private Lock lock new ReentrantLock();private Condition FirstCond lock.newCondition();private Condition SecondCond lock.newCondition();所以真正的 AQS 任务中一般是一个任务队列 N 个等待队列的因此我们尽量调用 signal 而少用 signalAll因为在指定的实例化等待队列中只有一个可以拿到锁的。 3.1.4总结 状态管理AQS 内部维护了一个状态变量state通过该状态变量来表示共享资源的状态可以是独占模式也可以是共享模式。CAS 操作AQS 使用 CASCompare And Swap操作来实现对状态变量的原子性修改确保线程安全性。线程阻塞和唤醒当一个线程尝试获取锁或访问资源时如果资源已被其他线程占用则会将该线程阻塞并加入同步等待队列直到资源可用时再唤醒线程。双向链表AQS 使用双向链表来管理等待线程保持线程之间的先后顺序即按照先进先出的原则进行访问。模板方法设计模式AQS 提供了模板方法允许子类通过实现特定的方法来控制锁的获取和释放过程从而实现不同类型的同步器。 3.2ReentrantLock ReentrantLock重入锁是JDK5中添加在并发包下的一个高性能的工具。 顾名思义ReentrantLock支持同一个线程在未释放锁的情况下重复获取锁。 3.2.1Synchronized和ReentrantLock 1性能上的比较 首先ReentrantLock的性能要优于synchronized。下面通过两段代码比价一下。 首先是synchronized PS当存在大量线程竞争锁时多数情况下ReentrantLock的性能优于synchronized。 因为在JDK6中对synchronized做了优化 在锁竞争不激烈的时候多数情况下锁会停留在偏向锁和轻量级锁阶段这两个阶段性能是很好的。 当存在大量竞争时可能会膨胀为重量级锁性能下降此时的ReentrantLock应该是优于synchronized的。 2获取公平锁 公平性是啥概念呢如果是公平的获取锁就是说多个线程之间获取锁的时候要排队依次获取锁如果是不公平的获取锁就是说多个线程获取锁的时候一哄而上谁抢到是谁的。 由于synchronized是基于monitor机制实现的它只支持非公平锁 但ReentrantLock同时支持公平锁和非公平锁。 3综述 ReentrantLock还有一些其他synchronized不具备的特性这里来总结一下。 3.2.2可重入功能的实现原理 ReentrantLock的实现基于队列同步器AbstractQueuedSynchronizer后面简称AQS ReentrantLock的可重入功能基于AQS的同步状态state。 核心原理当某一线程获取锁后将state值1并记录下当前持有锁的线程 再有线程来获取锁时判断这个线程与持有锁的线程是否是同一个线程如果是将state值再1如果不是阻塞线程。 当线程释放锁时将state值-1 当state值减为0时表示当前线程彻底释放了锁然后将记录当前持有锁的线程的那个字段设置为null并唤醒其他线程使其重新竞争锁。 // acquires的值是1 final boolean nonfairTryAcquire(int acquires) {// 获取当前线程final Thread current Thread.currentThread();// 获取state的值int c getState();// 如果state的值等于0表示当前没有线程持有锁// 尝试将state的值改为1如果修改成功则成功获取锁并设置当前线程为持有锁的线程返回trueif (c 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}// state的值不等于0表示已经有其他线程持有锁// 判断当前线程是否等于持有锁的线程如果等于将state的值1并设置到state上获取锁成功返回true// 如果不是当前线程获取锁失败返回falseelse if (current getExclusiveOwnerThread()) {int nextc c acquires;if (nextc 0) // overflowthrow new Error(Maximum lock count exceeded);setState(nextc);return true;}return false; }3.2.3非公平锁的实现原理 ReentrantLock有两个构造函数 // 无参构造默认使用非公平锁NonfairSync public ReentrantLock() {sync new NonfairSync(); }// 通过fair参数指定使用公平锁FairSync还是非公平锁NonfairSync public ReentrantLock(boolean fair) {sync fair ? new FairSync() : new NonfairSync(); }sync是ReentrantLock的成员变量是其内部类Sync的实例。NonfairSync和FairSync都是Sync类的子类。可以参考如下类关系图 Sync继承了AQS所以他具备了AQS的功能。同样的NonfairSync和FairSync都是AQS的子类。 当我们通过无参构造函数获取ReentrantLock实例后默认用的就是非公平锁。 1加锁 下面将通过如下场景描述非公平锁的实现原理假设一个线程(t1)获取到了锁其他很多没获取到锁的线程(others_t)加入到了AQS的同步队列中等待当这个线程执行完释放锁后其他线程重新非公平的竞争锁。 注意新来的线程执行lock方法时都要尝试下能不能直接获取锁若获取锁成功则记录当前线程否则调用AQS的acqurire方法进入到同步队列中等待 final void lock() {// 线程t1成功的将state的值从0改为1表示获取锁成功// 并记录当前持有锁的线程if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());else// others_t线程们没有获取到锁acquire(1); }如果获取锁失败会调用AQS的acquire方法 public final void acquire(int arg) {// tryAcquire是个模板方法在NonfairSync中实现如果在tryAcquire方法中依然获取锁失败会将当前线程加入同步队列中等待addWaiterif (!tryAcquire(arg) acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt(); }tryAcquire的实现如下其实是调用了上面的nonfairTryAcquire方法 protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires); }2释放锁 OK此时t1获取到了锁others_t线程们都跑到同步队列里等着了。 某一时刻t1自己的任务执行完成调用了释放锁的方法unlock。 public void unlock() {// 调用AQS的release方法释放资源sync.release(1); } public final boolean release(int arg) {// tryRelease也是模板方法在Sync中实现if (tryRelease(arg)) {Node h head;if (h ! null h.waitStatus ! 0)// 成功释放锁后唤醒同步队列中的下一个节点使之可以重新竞争锁// 注意此时不会唤醒队列第一个节点之后的节点这些节点此时还是无法竞争锁unparkSuccessor(h);return true;}return false; } protected final boolean tryRelease(int releases) {// 将state的值-1如果-1之后等于0释放锁成功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; }这时锁被释放了被唤醒的线程一个和新来的线程重新竞争锁不包含同步队列后面的那些线程。 回到lock方法中由于此时所有线程都能通过CAS来获取锁并不能保证被唤醒的那个线程能竞争过新来的线程所以是非公平的。这就是非公平锁的实现。 这个过程大概可以描述为下图这样子 3.2.4公平锁的实现原理 公平锁与非公平锁的释放锁的逻辑是一样的都是调用上述的unlock方法最大区别在于获取锁的时候直接调用的AQS的acquire方法没有先尝试获取锁。 static final class FairSync extends Sync {private static final long serialVersionUID -3000897897090466540L;// 获取锁与非公平锁的不同的地方在于这里直接调用的AQS的acquire方法没有先尝试获取锁// acquire又调用了下面的tryAcquire方法核心在于这个方法final void lock() {acquire(1);}/*** 这个方法和nonfairTryAcquire方法只有一点不同在标注为#1的地方* 多了一个判断hasQueuedPredecessors这个方法是判断当前AQS的同步队列中是否还有等待的线程* 如果有返回true否则返回false。* 由此可知当队列中没有等待的线程时当前线程才能尝试通过CAS的方式获取锁。* 否则就让这个线程去队列后面排队。*/protected final boolean tryAcquire(int acquires) {final Thread current Thread.currentThread();int c getState();if (c 0) {// #1if (!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.4tryLock原理 tryLock做的事情很简单让当前线程尝试获取一次锁成功的话返回true否则false。 其实就是调用了nonfairTryAcquire方法来获取锁。 public boolean tryLock() {return sync.nonfairTryAcquire(1); }至于获取失败的话他也不会将自己添加到同步队列中等待直接返回false让业务调用代码自己处理。 3.2.5可中断的获取锁 中断也就是通过Thread的interrupt方法将某个线程中断中断一个阻塞状态的线程会抛出一个InterruptedException异常。 如果获取锁是可中断的当一个线程长时间获取不到锁时我们可以主动将其中断可避免死锁的产生。 其实现方式如下 public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1); }会调用AQS的acquireInterruptibly方法 public final void acquireInterruptibly(int arg)throws InterruptedException {// 判断当前线程是否已经中断如果已中断抛出InterruptedException异常if (Thread.interrupted())throw new InterruptedException();if (!tryAcquire(arg))doAcquireInterruptibly(arg); }此时会优先通过tryAcquire尝试获取锁如果获取失败会将自己加入到队列中等待并可随时响应中断。 private void doAcquireInterruptibly(int arg)throws InterruptedException {// 将自己添加到队列中等待final Node node addWaiter(Node.EXCLUSIVE);boolean failed true;try {// 自旋的获取锁for (;;) {final Node p node.predecessor();if (p head tryAcquire(arg)) {setHead(node);p.next null; // help GCfailed false;return;}// 获取锁失败在parkAndCheckInterrupt方法中通过LockSupport.park()阻塞当前线程// 并调用Thread.interrupted()判断当前线程是否已经被中断// 如果被中断直接抛出InterruptedException异常退出锁的竞争队列if (shouldParkAfterFailedAcquire(p, node) parkAndCheckInterrupt())// #1throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);} }PS不可中断的方式下代码#1位置不会抛出InterruptedException异常只是简单的记录一下当前线程被中断了。 3.2.6可超时的获取锁 通过如下方法实现timeout是超时时间unit代表时间的单位毫秒、秒… public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout)); }可以发现这也是一个可以响应中断的方法。然后调用AQS的tryAcquireNanos方法 public final boolean tryAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();return tryAcquire(arg) ||doAcquireNanos(arg, nanosTimeout); }doAcquireNanos方法与中断里面的方法大同小异下面在注释中说明一下不同的地方 private boolean doAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (nanosTimeout 0L)return false;// 计算超时截止时间final long deadline System.nanoTime() nanosTimeout;final Node node addWaiter(Node.EXCLUSIVE);boolean failed true;try {for (;;) {final Node p node.predecessor();if (p head tryAcquire(arg)) {setHead(node);p.next null; // help GCfailed false;return true;}// 计算到截止时间的剩余时间nanosTimeout deadline - System.nanoTime();if (nanosTimeout 0L) // 超时了获取失败return false;// 超时时间大于1000纳秒时才阻塞// 因为如果小于1000纳秒基本可以认为超时了系统调用的时间可能都比这个长if (shouldParkAfterFailedAcquire(p, node) nanosTimeout spinForTimeoutThreshold)LockSupport.parkNanos(this, nanosTimeout);// 响应中断if (Thread.interrupted())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);} }3.2.7小结 本文首先对比了元老级的锁synchronized与ReentrantLock的不同ReentrantLock具有一下优势 同时支持公平锁与非公平锁 支持尝试非阻塞的一次性获取锁 支持超时获取锁 支持可中断的获取锁 * 支持更多的等待条件Condition 然后介绍了几个主要特性的实现原理这些都是基于AQS的。 首先ReentrantLock 采用了独占模式即同一时刻只允许一个线程持有锁。这保证了被锁保护的临界区只能被一个线程访问从而避免了多个线程同时修改共享资源导致的数据竞争和不一致性。ReentrantLock的核心是通过修改AQS中state的值来同步锁的状态。 通过这个方式实现了可重入。ReentrantLock具备公平锁和非公平锁默认使用非公平锁。其实现原理主要依赖于AQS中的同步队列。 最后可中断的机制是内部通过Thread.interrupted()判断当前线程是否已被中断如果被中断就抛出InterruptedException异常来实现的。
http://www.pierceye.com/news/624888/

相关文章:

  • 企业网站制作及cms技术wordpress站点 HTML
  • 网络宣传网站建设制作加盟网络推广方案怎么写
  • 花店网站建设毕设介绍wordpress批量导入txt
  • 上海市网站建设定制百度推广怎么优化关键词的质量
  • 建设工程质量检测公司网站html5 响应式音乐网站
  • 网站建设托管推广海报中文域名做的网站
  • 临沂专业网站建设公司哪家好网站建设的网页
  • 当牛做吗网站源代码分享百度云帝国怎么做网站
  • 简约网站欣赏做美食网站赚钱吗
  • 一叶子网站建设目标教育平台oss做视频网站
  • 购物网站开发流程图wordpress 批量注册
  • 如何做网站优化的内容google网站推广
  • 网站模版亮点北京电商网站开发费用
  • 南昌专业的企业网站建设公司wordpress源码在哪
  • 农家院做宣传应该在哪个网站营销代码查询
  • 大型企业网站设计案例晋江做网站的公司哪家好
  • 海外模板网站有哪些全国网页设计大赛
  • 网站设计常州注册公司没有地址怎么弄
  • 注销建设工程规划许可证在哪个网站wordpress+Apache升级
  • 视频网站如何做盗链青岛商城网站开发
  • 网站主色调googleapis wordpress
  • 作网站番禺区网络推广渠道
  • app开发网站排行app制作平台排行
  • 盐城网站建设找哪家好个人如何做短视频网站
  • 域名进行网站备案吗2023年重启核酸
  • 为什么几年前做的网站视频看不了wordpress图片标签
  • 做照片用的视频模板下载网站好网站源代码购买
  • 网站rss生成上海网页网络技术有限公司
  • 白山北京网站建设遂宁网站优化
  • 青岛网站建站公司银川网站建站公司