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

百度网站怎么用wordpress 前端投稿

百度网站怎么用,wordpress 前端投稿,wordpress地址如何修改密码,海口建设局网站目录 AQS底层源码深度剖析-Lock锁 ReentrantLock底层原理 为什么把获取锁失败的线程加入到阻塞队列中#xff0c;而不是采取其它方法#xff1f; 总结#xff1a;三大核心原理 CAS是啥#xff1f; 代码模拟一个CAS#xff1a; 公平锁与非公平锁 可重入锁的应用场景而不是采取其它方法 总结三大核心原理 CAS是啥 代码模拟一个CAS 公平锁与非公平锁 可重入锁的应用场景 AQS底层源码分析[重点难点] 类图展示 AQS类属性分析 AQS类中Node内部节点类 一获取锁 lock() 概念 源码深度剖析 二释放锁 unlock() 概念 源码深度剖析 三中断interrupt() 与LockSupport.park()LockSupport.park(Object obj)的关系【重点】 首先要明白以下三个API 其次要明白 提出问题为什么需要中断方法interrupt()的调用 代码示例1原生park()和unpark()的使用 代码示例2原生park()和unpark() 结合 interrupt相关的API 的使用 代码示例三在代码示例二的基础上加上一个interrupted方法 重点 LockSupport.park(Object obj)结合AQS底层源码剖析 得出结论 四lockInterruptibly()深度剖析 概念 源码深度剖析 总结lock()与lockInterruptibly()里面中断(interrupt)信号的实际应用场景【重点】 lock() lockInterruptibly() AQS底层源码深度剖析-Lock锁 ReentrantLock底层原理 为什么把获取锁失败的线程加入到阻塞队列中而不是采取其它方法 1.sleep休眠不可取因为获取锁的线程执行业务多久是不确定的所以获取锁失败的线程的休眠时间是不确定的。 2.让出CPU资源不可取让给谁 3.直接挂起不可取直接挂起等于说性能相当于重量级锁把对未获取锁线程的管理的任务交给了操作系统操作系统需要进行切换状态(从用户态切换回内核态)是极其耗费性能的。 所以我们把未获取锁成功的线程加入到一个阻塞队列中等到获取锁的线程执行完任务后可以去唤醒这些阻塞的线程。 总结三大核心原理 自旋LockSuportCAS(高并发也可以保证原子性) 【 queue队列存储进入的线程实现公平锁机制。】 分析自旋就是一直while循环尝试获取锁。 LockSupport就是阻塞线程与唤醒线程阻塞是为了降低自旋以此降低CPU所消耗的性能。 CAS就是在多线程同时操作时保证操作的原子性同时一刻只能有一个线程修改主内存的数据成功。 CAS是啥 代码模拟一个CAS /*** Description: TODO* Author: etcEriksen* Date: 2023/3/5**/ SuppressWarnings({all}) Slf4j public class Juc04_Thread_Cas {/*** state标识当前加锁状态记录加锁的次数* 默认加锁次数为0*/private volatile int state 0 ;private static CyclicBarrier cyclicBarrier new CyclicBarrier(5) ;private static Juc04_Thread_Cas cas new Juc04_Thread_Cas() ;static class Worker implements Runnable {Overridepublic void run() {log.info(请求:{}到达预定点,准备开始抢state:),Thread.currentThread().getName());try {//阻塞所有的线程到这里然后一起执行后面的逻辑操作cyclicBarrier.await();if (cas.compareAndSwapState(0,1)) {log.info(当前请求:{},抢到锁!,Thread.currentThread().getName());}else{log.info(当前请求:{},抢锁失败!,Thread.currentThread().getName());}} catch (Exception e) {e.printStackTrace();}}}public final boolean compareAndSwapState(int oldValue,int newValue) {/*** 比较stateOffset的值和oldValue值是否一致若不一致那么不可修改 。如果一致那么修改值为newValue。*/return unsafe.compareAndSwapInt(this,stateOffset,oldValue,newValue);}private static final Unsafe unsafe UnsafeInstance.reflectGetUnsafe();private static final long stateOffset;static {try {stateOffset unsafe.objectFieldOffset(Juc04_Thread_Cas.class.getDeclaredField(state));} catch (Exception e) {throw new Error();}} }public class UnsafeInstance {public static Unsafe reflectGetUnsafe() {try {Field field Unsafe.class.getDeclaredField(theUnsafe);field.setAccessible(true);return (Unsafe) field.get(null);} catch (Exception e) {e.printStackTrace();}return null;}public static void main(String[] args) {int j1;reflectGetUnsafe().loadFence();int i 0;} } 公平锁与非公平锁 t-0正在CAS执行任务逻辑当执行完的那一刻t-4正好进入了那么如果是非公平锁那么t-4不用到阻塞队列的最后去排队而是直接去抢t-0线程执行完任务后进行释放的锁对象。如果是公平锁那么t-4就会进入阻塞队列老老实实的排到队尾等待。 可重入锁的应用场景 AQS底层源码分析[重点难点] 类图展示 AQS类属性分析 注释state为锁的状态器。eg无锁状态时state0。同一线程每成功获取该锁一次则state1同一线程每释放该锁对象一次则state-1。 exclusiveOwnerThread: 表示当前持有锁对象的线程为谁 head和tail就是在维护一个双端队列后面该队列用来存储获取锁失败的线程。 AQS类中Node内部节点类 注释prev和next分别表示当前Node节点的前驱和后继节点 waitStatusNode节点的生命状态信号量。表示Node节点在不同生命状态下所呈现出的不同性质有五种如下 SIGNAL -1 //可被唤醒         CANCELLED 1 //代表出现异常中断引起的需要废弃结束         CONDITION -2 // 条件等待         PROPAGATE -3 // 传播         0 - 初始状态Init状态 thread由于我们是使用多个Node节点组成一个双端阻塞队列队列中的每一个元素都是一个Node每一个Node对应维护一个线程对象所以我们需要在Node节点类中维护一个Thread类属性thread 。 一获取锁 lock() 概念 这种lock()获取锁对象的方式必须等持有锁对象的线程做完事情其他等待的线程才可以做事情。而且中途不能退出会一直阻塞存储在CLH双端队列中。 说详细点就是当一个节点对象加入到CLH双端阻塞队列中后在被持有锁对象唤醒之前它中途就不能退出该队列即使阻塞队列中节点对应的线程对象被中断也不可以退出那么对队列中节点对应线程的中断有啥作用呢最后的总结lock()和lockInterruptibly()会举例细说 源码深度剖析 1. 如果锁未被另一个线程持有则获取锁并立即返回将锁保持计数设置为 1。 如果当前线程已持有锁则保留计数将递增 1并且该方法会立即返回。 如果锁由另一个线程持有则当前线程将出于线程调度目的而被禁用并处于休眠状态直到获取锁为止此时锁保持计数设置为 1。 2. 3. 4. 接下来会详细分析tryAcquire和acquireQueued这两个方法 tryAcquire方法解析 tryAcquire方法中调用的hasQueuePredecessors方法的解析 acquireQueued方法解析 acquireQueued调用的addWaiter方法解析 addWaiter调用的enq()方法解析 提出一个疑问和思考 当队列初始化完毕时为什么在addWaiter方法中已经做了插入新Node到队列中的操作然而又在addWaiter调用的enq方法中又重复做了一次插入新Node节点到队列中的操作呢 答案因为并发多线程环境 acquireQueued方法解析 acquireQueued方法调用的shouldParkAfterFailedAcquire方法解析: acquireQueued方法调用的parkAndCheckInterrupt方法解析 为什么要把第一个真实节点的状态设置在虚拟头节点的waitStatus上为什么不设计在自己节点所维护的waitStatus呢 首先你应该明白一个点我们是公平锁所谓公平锁就是先来的先可以获取到锁对象后来的只能在后面排队等。 所以我们构建出了一个有序的阻塞队列后来的线程插在最后面第一个真实节点(虚拟节点的下一个节点)就是下一次锁对象的持有者。 当锁对象释放后每次都是把锁对象分配给第一个真实节点(即虚拟头节点的下一个节点)这就是保证了公平。 第一个真实节点获取到锁对象后会转变为虚拟头节点(此时waitStatus0)原来的虚拟头节点会被GC回收掉。此时只需把新虚拟节点的waitStatus改为-1即可因为waitStatus维护的是Node节点的性质所以最好维护在虚拟头节点。 为什么要费尽心思搞出一个waitStatus并且设置为-1 因为waitStatus-1就是代表一个Node节点的状态量代表的是可以进行被唤醒那么在释放锁的时候我们只需进行检验该waitStatus是否为-1为-1那么才可以去释放锁 才可以去唤醒该线程对应的Node节点。 二释放锁 unlock() 概念 就是当前锁持有者对应的线程执行锁对象的释放并且通知唤醒阻塞队列中的第一个真实节点对应的线程对象(即虚拟头节点Head的下一个节点)。 在公平锁的实现下释放的锁对象肯定是被排在阻塞队列中的第一个节点对应的线程获取。但是在非公平锁的实现下释放的锁对象可能会被刚刚进入的线程竞争获取到导致阻塞队列第一个节点对应的线程对象获取锁对象失败。 源码深度剖析 1. 2. 3.release方法解析 release方法调用的tryRelease方法解析 release方法调用的unparkSuccessor方法解析 unparkSuccessor方法执行唤醒线程的操作后会唤醒加锁过程中调用的parkAndCheckInterrupt方法中阻塞的线程 parkAndCheckInterrupt阻塞的线程被唤醒后说明parkAndCheckInterrupt阻塞完毕 即执行完毕那么再一次循环向上如图分析 为什么要在 unparkSuccessor 方法中把Head虚拟头节点的waitStatus从-1改为0 其实也说的很清楚了。 重复一遍释放锁唤醒线程的逻辑t1线程执行完业务后进行释放锁并且通知唤醒阻塞队列中阻塞着的t2线程在唤醒之前需要把阻塞队列虚拟头节点Head的waitStatus由-1改为0。 但是在非公平锁的情况下可能阻塞队列的第一个Node对应的t2线程在获取锁的时候 有其它线程进入跟它竞争锁可能t2线程获取锁失败。获取锁成功那好说。 如果t2线程获取锁失败t2线程会进行两次循环【第二次循环是逻辑关键阻塞前最后一次尝试获取锁若成功那么就无需阻塞啦极大的节省性能】 第一次循环由于t2线程获取锁失败那么执行的acquireQueued方法中执行调用tryAcquire方法返回false。t2线程会再一次进入到shouldParkAfterFailedAcquire方法中由于Head的waitStatus被t1线程在释放锁的时候改为了0所以shouldParkAfterFailedAcquire方法中会执行逻辑把waitStatus改为-1并且返回false。 第二次循环会在阻塞前再一次的进行尝试获取锁(tryAcquire)因为阻塞是重型操作需要切换状态所以阻塞之前再一次进行尝试获取锁(做最后一次尝试)如果获取锁还是失败那么就进行阻塞循环结束。 假设说t1线程释放锁后在唤醒t2之前不把阻塞队列虚拟头节点Head的waitStatus由-1改为0。那么t2线程只会进行一次循环那么就不可能完成阻塞前最后一次tryAcquire尝试获取锁的功能啦 三中断interrupt() 与LockSupport.park()LockSupport.park(Object obj)的关系【重点】 对于第三点我们依旧结合AQS底层源码进行分析前面一(获取锁)和二(释放锁)这两大方面分别代表了AQS源码的逻辑主线第三点算是对前面两点中涉及到interrupt中断源码的分析与补充。 首先要明白以下三个API 1.Thread.currentThread().interrupt()表示为当前线程打一个中断标记中断当前线程。 2.Thread.interrupted()表示清除中断标记如果当前线程被中断了返回true。否则返回false 3.Thread.currentThread().isInterrupted()表示查看当前线程的状态是否中断不清除中断标记 其次要明白 对于AQS底层我们调用unlock()方法的底层就是调用LockSupport.park(Object obj)的 LockSupport.park()与LockSupport.park(Object obj)这两个方法还有所不同的。 LockSupport.park()方法在执行park()方法之前先进行检验当前线程t1是否有中断标识如果没有那么标识着当前t1线程要被阻塞住不能向下执行。 所谓中断标识就是如果在其它线程中执行t1.interrupt()中断阻塞着的park方法那么就会给当前线程t1分配一个中断标识就会停止阻塞向下继续执行。 但是当我们执行Thread.currentThread().interrupted()后就会消除该中断标识那么当下一次park()执行前进行检验中断标识时 发现没有那么就会继续阻塞住。 LockSupport.park(Object obj)方法它与LockSupport.park()方法相同obj标识阻塞等待的对象 提出问题为什么需要中断方法interrupt()的调用 分析 interrupt方法为中断线程的方法api可以中断线程的阻塞。即是中断LockSupport.park()对线程的阻塞也可以中断Lock.park(Object obj)对线程的阻塞。 之前是如何中断线程的使用的是底层的stop方法就好比linux系统下的kill -9 操作无论是jdk提供的stop还是linux的kill都是极其的暴力的会立刻杀死当前线程(线程是进程的组成部分)假设业务执行一半被强制杀死了那么就是十分危险的。 所以我们寻求一种柔和的中断方式可以给我们判断的机会来自定义何时进行退出以此保证业务的安全退出与执行因此引出interrupt方法isInterrupted方法来保证自定义退出逻辑 首先使用interrupt()方法进行中断阻塞后会给中断阻塞的线程一个中断标识标识该线程已经中断啦。 然后我们就可以结合Thread.currentThread().isInterrupted()方法进行查看当前线程是否已经中断如果别处已经把该线程中断(即调用interrupt()方法)那么我们就要执行退出。如果判断出该线程未中断那么继续执行业务。 代码示例1原生park()和unpark()的使用 /*** Description: TODO* Author: etcEriksen* Date: 2023/3/6**/ SuppressWarnings({all}) Slf4j public class demo2 {public static void main(String[] args) {Thread t1 new Thread(() - {while (true) {log.info(开始阻塞);LockSupport.park();log.info(阻塞结束);log.info(若不中断unpark执行完那么执行业务逻辑);}});t1.start();try {Thread.sleep(2000);log.info(中断线程);LockSupport.unpark(t1);} catch (InterruptedException e) {e.printStackTrace();}log.info(main线程执行结束);}} 代码分析 比对运行结果与分析一致 代码示例2原生park()和unpark() 结合 interrupt相关的API 的使用 记住两个点 (1) interrupt()方法是给线程一个标记你这个线程已经被附上一个阻断标识了啊你再park()阻塞也没用不会阻塞的哈 (2) interrupt()进行中断后会给线程做一个中断标识我们可以调用isInterrupted这个方法去自定义自己的逻辑中断后去做啥逻辑退出还是执行其它业务这些都由你自己决定再一次验证了前面的结论这是一个自定义的是柔和的中断。 /*** Description: TODO* Author: etcEriksen* Date: 2023/3/6**/ SuppressWarnings({all}) Slf4j public class demo2 {public static void main(String[] args) {Thread t1 new Thread(() - {while (true) {log.info(开始阻塞);LockSupport.park();log.info(阻塞结束);if (Thread.currentThread().isInterrupted()) {//再一次执行park()是为了表明只要该线程被标识了中断标记那么park()执行多少次也不会阻塞的LockSupport.park();log.info(中断退出不执行后面的业务逻辑);}log.info(若不中断unpark执行完那么执行业务逻辑);}});t1.start();try {Thread.sleep(2000);log.info(中断线程);t1.interrupt();//LockSupport.unpark(t1);} catch (InterruptedException e) {e.printStackTrace();}log.info(main线程执行结束);}}代码分析 代码运行结果一直死循环打印输出没有尽头 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 若不中断unpark执行完那么执行业务逻辑 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 开始阻塞 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 阻塞结束 17:19:15.853 [Thread-0] INFO com.messi.leo.AQS.lock.demo2 - 中断退出不执行后面的业务逻辑代码示例三在代码示例二的基础上加上一个interrupted方法 记住一个点 interrupted方法就是消除当前调用方法的线程对象的中断标识。那么当线程的中断标识被消除成功时我们再一次park()线程就会被阻塞掉 返回值为布尔类型若当前线程有中断标识那么返回true。否则返回false 代码演示 /*** Description: TODO* Author: etcEriksen* Date: 2023/3/6**/ SuppressWarnings({all}) Slf4j public class demo2 {public static void main(String[] args) {Thread t1 new Thread(() - {while (true) {log.info(开始阻塞);LockSupport.park();log.info(阻塞结束);if (Thread.currentThread().isInterrupted()) {boolean isInterrupted Thread.currentThread().interrupted();if (isInterrupted) {log.info(线程的中断标识被消除成功再一次park()执行时 线程就会被阻塞掉);}LockSupport.park();log.info(中断退出不执行后面的业务逻辑);}log.info(若不中断unpark执行完那么执行业务逻辑);}});t1.start();try {Thread.sleep(2000);log.info(中断线程);t1.interrupt();//LockSupport.unpark(t1);} catch (InterruptedException e) {e.printStackTrace();}log.info(main线程执行结束);}} 代码分析 代码输出 重点 LockSupport.park(Object obj)结合AQS底层源码剖析 ReentrantLock类对应的加锁流程 1. 2. 3. 4. 5. 6. 7. ReentrantLock类对应的释放锁流程 1. 2. 得出结论 unpark和interrupt方法都可以进行停止park方法的线程阻塞。 但是interrupt不同之处在于它给线程对象分配了一个中断标识当下一次进行park时判断出当前线程对象存在该中断标识那么就不会park阻塞因此我们可以使用interrupted方法进行消除线程对象的中断标识 四lockInterruptibly()深度剖析 概念 lockInterruptibly()方法和lock方法一致也必须是等待持有锁对象的线程做完事情其他线程才能做事情但中途可以进行退出。 说详细点就是当节点(线程封装在节点中)加入到阻塞队列中后若线程执行interrupt中断方法会抛出中断异常中途会从阻塞队列中进行退出表示获取锁失败waitStatus标记为1表示出现异常导致退出 源码深度剖析 1. 2. 3. 4. doAcquireInterruptibly方法调用的shouldParkAfterFailedAcquire方法解析与lock()底层的shouldParkAfterFailedAcquire方法一致不再详细赘述 doAcquireInterruptibly方法调用的 parkAndCheckInterrupt方法 解析 5. 6.cacelAcquire方法解析 至于这个方法的具体实现总结一句话就是对阻塞队列中出现异常的节点要进行从阻塞队列中移除并且抛出中断异常并且要进行修改节点对应waitStatus的值。具体怎么实现的画一张图一步步对照着走即可easy 总结lock()与lockInterruptibly()里面中断(interrupt)信号的实际应用场景【重点】 lock() 概念回顾 这种lock()获取锁对象的方式必须等持有锁对象的线程做完事情其他等待的线程才可以做事情。而且中途不能退出会一直阻塞存储在CLH双端队列中。 说详细点就是当一个节点对象加入到CLH双端阻塞队列中后在被持有锁对象唤醒之前它中途就不能退出该队列即使阻塞队列中节点对应的线程对象被中断也不可以退出 lockI()底层的CLH阻塞队列中Node节点对应的线程对应的中断信号有啥用 实际案例证明:还是追源码中间省略了很多easy代码只保留了关键处 selfInterrupt方法对当前线程的中断有啥用我在搞笑吗 回到API调用的应用层 如下图画红圈就是作用我们可以跳过interrupted()方法得到中断的信号去自定义业务逻辑很重要的一个点 lockInterruptibly() 概念回顾 方法和lock方法一致也必须是等待持有锁对象的线程做完事情其他线程才能做事情但中途可以进行退出。 说详细点就是当节点(线程封装在节点中)加入到阻塞队列中后若线程执行interrupt中断方法会抛出中断异常中途会从阻塞队列中进行退出表示获取锁失败waitStatus标记为1表示出现异常导致退出 lockInterruptibly()底层的CLH阻塞队列中Node节点对应的线程对应的中断信号有啥用 实际案例证明:还是追源码中间省略了很多easy代码只保留了关键处 回到API调用的应用层 初次学习AQS底层源码可能理解不深刻。若有不对期待指正。
http://www.w-s-a.com/news/699011/

相关文章:

  • 东莞企业免费模版网站建设一般网站维护要多久
  • 著名建筑设计网站常州制作网站价格
  • 食品营销型网站广东省广州市白云区
  • 如何做网站哪个站推广描述对于营销型网站建设很重要飘红效果更佳
  • 济阳做网站公司99企业邮箱888
  • 国贸做网站的公司能接做网站的活的网站
  • 淮南建设厅网站上杭县建设局网站
  • 东莞做网站公司首选!西安注册公司费用
  • 做网站包括什么卖水果网站模板
  • 扬州网站建设外包wordpress 文章评分
  • 网站建设网站多少钱公司名字大全列表
  • 设计企业网站内容wordpress 投稿者 权限
  • seo网站推广免费价格低的成语
  • 做网站建设销售辛苦吗专题页是什么
  • 做网站的软件名字全拼wordpress可以上传文件吗
  • 建品牌网站公司关于asp_sql网站开发的书籍
  • 建网站公司营销型网站建设wordpress自定义登录页
  • 泉州市住房和城乡建设局网站淘宝店网站怎么做
  • 企业网站建设费未付款怎样挂账长春网站制作专业
  • 深圳找网站建设邹城市建设局网站
  • 长春火车站停运了吗网站开发概要设计
  • 网站开发表格整体页面居中网站域名详解
  • 漕泾网站建设赢展网站建设
  • 医院网站建设的要求毕业了智慧团建密码忘了
  • 网站怎么建设在哪里接单坪山商城网站建设哪家便宜
  • 中山企业网站优化易语言wordpress发布
  • 宜昌网站推广自己怎么做彩票网站吗
  • 英文网站建设 招标网站建设中服务器搭建方式
  • 直播网站建设需要什么软件有哪些室内设计效果图怎么做
  • 宁波网站建设电话网络推广外包一年多少钱