一、标准用法

1 常用API

方法名称 描述
void lock() 获取锁,调用该方法当前线程将会获取锁,当锁获得后,从该方法返回
void lockInterruptibly() throws InterruptedException 可中断地获取锁,和 lock0 方法的不同之处在于该方法会响应中断,即在锁的获取中可以中断当前线程
boolean tryLock() 尝试非阻塞的获取锁,调用该方法后立刻返回,如果能够获取则返回 tnue,否则返回 false
boolean tryLock(long) time. Time Unit unit) throws InterruptedException 超时的获取锁,当前线程在以下3 种情况下会返回:当前线程在超时时间内获得了锁;当前线程在超时时间内被中断;超时时间结束,返回 false
void unlock() 释放锁
package com.sonny.classexercise.concurrent.lock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @author Xionghaijun* @date 2022/11/9 22:53*/
@Slf4j
public class ConditionTest {public static void main(String[] args) {Lock lock = new ReentrantLock();Condition condition = lock.newCondition();new Thread(() -> {lock.lock();try {log.debug(Thread.currentThread().getName() + " 开始处理任务");//会释放当前持有的锁,然后阻塞当前线程condition.await();log.debug(Thread.currentThread().getName() + " 结束处理任务");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}).start();new Thread(() -> {lock.lock();try {log.debug(Thread.currentThread().getName() + " 开始处理任务");Thread.sleep(2000);//唤醒因调用Condition#await方法而阻塞的线程condition.signal();log.debug(Thread.currentThread().getName() + " 结束处理任务");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}).start();}}----------------
20:44:48.110 [Thread-0] DEBUG com.sonny.classexercise.concurrent.lock.ConditionTest - Thread-0 开始处理任务
20:44:48.117 [Thread-1] DEBUG com.sonny.classexercise.concurrent.lock.ConditionTest - Thread-1 开始处理任务
20:44:50.121 [Thread-1] DEBUG com.sonny.classexercise.concurrent.lock.ConditionTest - Thread-1 结束处理任务
20:44:50.121 [Thread-0] DEBUG com.sonny.classexercise.concurrent.lock.ConditionTest - Thread-0 结束处理任务

2 ReentrantLock详解

ReentrantLock是一种基于AQS框架的应用实现,是JDK中的一种线程并发访问的同步手 段,它的功能类似于synchronized是一种互斥锁,可以保证线程安全。

相对于 synchronized, ReentrantLock具备如下特点:

  • 可中断
  • 可设置超时时间
  • 可以设置为公平锁
  • 支持多个条件变量
  • 与 Synchronized 一样,都支持可在重入(被锁代码块中再次加锁)

Synchronized与ReentrantLock区别:

  • Synchronized是JVM层次的锁实现,ReentrantLockshiJDK层次的锁实现;
  • Synchronized的锁状态无法在代码中直接判断,ReentrantLock可通过 isLocked() 方法判断;
  • Synchronized是非公平锁,ReentrantLock可设置公平非公平;
  • Synchronized是不可被中断的,而ReentrantLock#lockInterruptiibly方法是可以被中断的;
  • 在发生异常时Synchronized会自动释放锁,而ReentrantLock需要在Finally块中显示释放锁;
  • ReentrantLock获取锁的形式有多种:如立即返回是否成功,或等待指定时长的获取,更加灵活;
  • Synchronized在特定情况下对于已经在等待的线程是后来的线程先获取锁,而ReentrantLock对于应经在等待的线程是先来的线程先获取锁。

可重入

package com.sonny.classexercise.concurrent.lock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.locks.ReentrantLock;/*** @author Xionghaijun* @date 2022/11/9 22:50*/
@Slf4j
public class ReentrantLockDemo2 {public static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {method1();}public static void method1() {lock.lock();try {log.debug("execute method1");method2();} finally {lock.unlock();}}public static void method2() {lock.lock();try {log.debug("execute method2");method3();} finally {lock.unlock();}}public static void method3() {lock.lock();try {log.debug("execute method3");} finally {lock.unlock();}}}------------
21:15:52.165 [main] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo2 - execute method1
21:15:52.192 [main] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo2 - execute method2
21:15:52.193 [main] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo2 - execute method3

可中断

package com.sonny.classexercise.concurrent.lock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.locks.ReentrantLock;/*** @author Xionghaijun* @date 2022/11/9 22:51*/
@Slf4j
public class ReentrantLockDemo3 {public static void main(String[] args) throws InterruptedException {ReentrantLock lock = new ReentrantLock();Thread t1 = new Thread(() -> {log.debug("t1启动...");try {lock.lockInterruptibly();try {log.debug("t1获得了锁");} finally {lock.unlock();}} catch (InterruptedException e) {e.printStackTrace();log.debug("t1等锁的过程中被中断");}}, "t1");lock.lock();try {log.debug("main线程获得了锁");t1.start();//先让线程t1执行Thread.sleep(1000);t1.interrupt();log.debug("线程t1执行中断");} finally {lock.unlock();}}}-----------------
21:18:38.880 [main] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo3 - main线程获得了锁
21:18:38.887 [t1] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo3 - t1启动...
21:18:39.890 [main] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo3 - 线程t1执行中断
21:18:39.892 [t1] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo3 - t1等锁的过程中被中断
java.lang.InterruptedExceptionat java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)at com.sonny.classexercise.concurrent.lock.ReentrantLockDemo3.lambda$main$0(ReentrantLockDemo3.java:22)at java.lang.Thread.run(Thread.java:748)

锁超时

package com.sonny.classexercise.concurrent.lock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;/*** 锁超时,立刻失败** @author Xionghaijun* @date 2022/11/9 22:51*/
@Slf4j
public class ReentrantLockDemo4 {public static void main(String[] args) throws InterruptedException {ReentrantLock lock = new ReentrantLock();Thread t1 = new Thread(() -> {log.debug("t1启动...");// 注意: 即使是设置的公平锁,此方法也会立即返回获取锁成功或失败,公平策略不生效
//            if (!lock.tryLock()) {//                log.debug("t1获取锁失败,立即返回false");
//                return;
//            }//超时try {if (!lock.tryLock(1, TimeUnit.SECONDS)) {log.debug("等待 1s 后获取锁失败,返回");return;}} catch (InterruptedException e) {e.printStackTrace();return;}try {log.debug("t1获得了锁");} finally {lock.unlock();}}, "t1");lock.lock();try {log.debug("main线程获得了锁");t1.start();//先让线程t1执行Thread.sleep(2000);} finally {lock.unlock();}}
}------------
21:26:04.418 [main] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo4 - main线程获得了锁
21:26:04.424 [t1] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo4 - t1启动...
21:26:05.431 [t1] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo4 - 等待 1s 后获取锁失败,返回

公平锁、非公平锁

package com.sonny.classexercise.concurrent.lock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.locks.ReentrantLock;/*** 公平锁** @author Xionghaijun* @date 2022/11/9 22:52*/
@Slf4j
public class ReentrantLockDemo5 {public static void main(String[] args) throws InterruptedException {//ReentrantLock lock = new ReentrantLock(true); //公平锁ReentrantLock lock = new ReentrantLock(); //非公平锁for (int i = 0; i < 100; i++) {new Thread(() -> {lock.lock();try {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}log.debug(Thread.currentThread().getName() + " running...");} finally {lock.unlock();}}, "t" + i).start();}// 1s 之后去争抢锁Thread.sleep(1000);for (int i = 0; i < 100; i++) {new Thread(() -> {lock.lock();try {log.debug(Thread.currentThread().getName() + " running...");} finally {lock.unlock();}}, "强行插入" + i).start();}}
}---------
公平锁
21:36:25.161 [t0] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t0 running...
21:36:25.177 [t1] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t1 running...
21:36:25.188 [t2] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t2 running...
21:36:25.199 [t3] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t3 running...
21:36:25.211 [t4] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t4 running...
21:36:25.224 [t5] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t5 running...
21:36:25.235 [t6] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t6 running...
21:36:25.245 [t7] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t7 running...
21:36:25.257 [t8] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t8 running...
21:36:25.268 [t9] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t9 running...
21:36:25.284 [t10] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t10 running...
21:36:25.302 [t11] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t11 running...
21:36:25.318 [t12] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t12 running...
21:36:25.330 [t13] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t13 running...
21:36:25.346 [t14] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t14 running...
21:36:25.360 [t15] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t15 running...
21:36:25.372 [t16] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t16 running...
21:36:25.384 [t17] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t17 running...
21:36:25.398 [t18] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t18 running...
21:36:25.410 [t19] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t19 running...
21:36:25.423 [t20] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t20 running...
21:36:25.434 [t21] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t21 running...
21:36:25.445 [t22] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t22 running...
21:36:25.456 [t23] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t23 running...
21:36:25.467 [t24] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t24 running...
21:36:25.479 [t25] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t25 running...
21:36:25.490 [t26] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t26 running...
21:36:25.509 [t27] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t27 running...
21:36:25.521 [t28] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t28 running...
21:36:25.545 [t29] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t29 running...
21:36:25.571 [t30] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t30 running...
21:36:25.592 [t31] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t31 running...
21:36:25.608 [t32] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t32 running...
21:36:25.619 [t33] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t33 running...
21:36:25.630 [t34] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t34 running...
21:36:25.642 [t35] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t35 running...
21:36:25.653 [t36] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t36 running...
21:36:25.664 [t37] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t37 running...
21:36:25.676 [t38] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t38 running...
21:36:25.687 [t39] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t39 running...
21:36:25.698 [t40] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t40 running...
21:36:25.709 [t41] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t41 running...
21:36:25.726 [t42] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t42 running...
21:36:25.738 [t43] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t43 running...
21:36:25.750 [t44] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t44 running...
21:36:25.762 [t45] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t45 running...
21:36:25.775 [t46] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t46 running...
21:36:25.788 [t47] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t47 running...
21:36:25.801 [t48] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t48 running...
21:36:25.812 [t49] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t49 running...
21:36:25.824 [t50] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t50 running...
21:36:25.835 [t51] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t51 running...
21:36:25.846 [t52] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t52 running...
21:36:25.856 [t53] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t53 running...
21:36:25.867 [t54] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t54 running...
21:36:25.879 [t55] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t55 running...
21:36:25.890 [t56] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t56 running...
21:36:25.901 [t57] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t57 running...
21:36:25.912 [t58] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t58 running...
21:36:25.923 [t59] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t59 running...
21:36:25.934 [t60] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t60 running...
21:36:25.947 [t61] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t61 running...
21:36:25.958 [t62] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t62 running...
21:36:25.969 [t63] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t63 running...
21:36:25.980 [t64] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t64 running...
21:36:25.991 [t65] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t65 running...
21:36:26.004 [t66] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t66 running...
21:36:26.022 [t67] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t67 running...
21:36:26.042 [t68] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t68 running...
21:36:26.056 [t69] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t69 running...
21:36:26.069 [t70] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t70 running...
21:36:26.080 [t71] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t71 running...
21:36:26.093 [t72] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t72 running...
21:36:26.106 [t73] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t73 running...
21:36:26.117 [t74] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t74 running...
21:36:26.128 [t75] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t75 running...
21:36:26.140 [t76] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t76 running...
21:36:26.150 [t77] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t77 running...
21:36:26.162 [t78] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t78 running...
21:36:26.174 [t79] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t79 running...
21:36:26.185 [t80] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t80 running...
21:36:26.200 [t81] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t81 running...
21:36:26.211 [t82] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t82 running...
21:36:26.223 [t83] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t83 running...
21:36:26.234 [t84] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t84 running...
21:36:26.248 [t85] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t85 running...
21:36:26.261 [t86] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t86 running...
21:36:26.274 [t87] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t87 running...
21:36:26.292 [t88] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t88 running...
21:36:26.309 [t89] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t89 running...
21:36:26.322 [t90] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t90 running...
21:36:26.381 [t91] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t91 running...
21:36:26.393 [t92] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t92 running...
21:36:26.404 [t93] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t93 running...
21:36:26.414 [t94] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t94 running...
21:36:26.424 [t95] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t95 running...
21:36:26.435 [t96] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t96 running...
21:36:26.446 [t97] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t97 running...
21:36:26.458 [t98] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t98 running...
21:36:26.469 [t99] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t99 running...
21:36:26.470 [强行插入0] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入0 running...
21:36:26.470 [强行插入1] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入1 running...
21:36:26.471 [强行插入2] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入2 running...
21:36:26.471 [强行插入3] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入3 running...
21:36:26.472 [强行插入4] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入4 running...
21:36:26.472 [强行插入5] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入5 running...
21:36:26.472 [强行插入6] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入6 running...
21:36:26.472 [强行插入7] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入7 running...
21:36:26.472 [强行插入8] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入8 running...
21:36:26.473 [强行插入9] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入9 running...
21:36:26.473 [强行插入10] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入10 running...
21:36:26.473 [强行插入11] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入11 running...
21:36:26.473 [强行插入12] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入12 running...
21:36:26.473 [强行插入13] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入13 running...
21:36:26.473 [强行插入14] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入14 running...
21:36:26.478 [强行插入15] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入15 running...
21:36:26.479 [强行插入16] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入16 running...
21:36:26.479 [强行插入17] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入17 running...
21:36:26.479 [强行插入18] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入18 running...
21:36:26.479 [强行插入19] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入19 running...
21:36:26.479 [强行插入20] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入20 running...
21:36:26.479 [强行插入21] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入21 running...
21:36:26.480 [强行插入22] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入22 running...
21:36:26.480 [强行插入23] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入23 running...
21:36:26.481 [强行插入24] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入24 running...
21:36:26.481 [强行插入25] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入25 running...
21:36:26.481 [强行插入26] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入26 running...
21:36:26.482 [强行插入27] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入27 running...
21:36:26.482 [强行插入28] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入28 running...
21:36:26.482 [强行插入29] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入29 running...
21:36:26.483 [强行插入30] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入30 running...
21:36:26.483 [强行插入31] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入31 running...
21:36:26.483 [强行插入32] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入32 running...
21:36:26.483 [强行插入33] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入33 running...
21:36:26.483 [强行插入34] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入34 running...
21:36:26.483 [强行插入35] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入35 running...
21:36:26.484 [强行插入36] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入36 running...
21:36:26.484 [强行插入37] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入37 running...
21:36:26.484 [强行插入38] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入38 running...
21:36:26.484 [强行插入39] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入39 running...
21:36:26.484 [强行插入40] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入40 running...
21:36:26.484 [强行插入41] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入41 running...
21:36:26.484 [强行插入42] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入42 running...
21:36:26.485 [强行插入43] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入43 running...
21:36:26.485 [强行插入44] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入44 running...
21:36:26.485 [强行插入45] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入45 running...
21:36:26.485 [强行插入46] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入46 running...
21:36:26.485 [强行插入47] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入47 running...
21:36:26.485 [强行插入48] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入48 running...
21:36:26.486 [强行插入49] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入49 running...
21:36:26.486 [强行插入50] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入50 running...
21:36:26.486 [强行插入51] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入51 running...
21:36:26.486 [强行插入52] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入52 running...
21:36:26.486 [强行插入53] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入53 running...
21:36:26.487 [强行插入54] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入54 running...
21:36:26.487 [强行插入55] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入55 running...
21:36:26.487 [强行插入56] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入56 running...
21:36:26.487 [强行插入57] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入57 running...
21:36:26.487 [强行插入58] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入58 running...
21:36:26.487 [强行插入59] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入59 running...
21:36:26.487 [强行插入60] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入60 running...
21:36:26.488 [强行插入61] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入61 running...
21:36:26.488 [强行插入62] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入62 running...
21:36:26.488 [强行插入63] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入63 running...
21:36:26.488 [强行插入64] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入64 running...
21:36:26.488 [强行插入65] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入65 running...
21:36:26.488 [强行插入66] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入66 running...
21:36:26.488 [强行插入67] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入67 running...
21:36:26.489 [强行插入68] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入68 running...
21:36:26.489 [强行插入69] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入69 running...
21:36:26.489 [强行插入70] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入70 running...
21:36:26.489 [强行插入71] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入71 running...
21:36:26.490 [强行插入72] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入72 running...
21:36:26.490 [强行插入73] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入73 running...
21:36:26.490 [强行插入74] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入74 running...
21:36:26.490 [强行插入75] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入75 running...
21:36:26.490 [强行插入76] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入76 running...
21:36:26.490 [强行插入77] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入77 running...
21:36:26.491 [强行插入78] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入78 running...
21:36:26.491 [强行插入79] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入79 running...
21:36:26.495 [强行插入80] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入80 running...
21:36:26.495 [强行插入81] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入81 running...
21:36:26.496 [强行插入82] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入82 running...
21:36:26.496 [强行插入83] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入83 running...
21:36:26.496 [强行插入84] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入84 running...
21:36:26.497 [强行插入85] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入85 running...
21:36:26.497 [强行插入86] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入86 running...
21:36:26.498 [强行插入87] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入87 running...
21:36:26.498 [强行插入88] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入88 running...
21:36:26.499 [强行插入89] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入89 running...
21:36:26.499 [强行插入90] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入90 running...
21:36:26.499 [强行插入91] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入91 running...
21:36:26.499 [强行插入92] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入92 running...
21:36:26.500 [强行插入93] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入93 running...
21:36:26.500 [强行插入94] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入94 running...
21:36:26.500 [强行插入95] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入95 running...
21:36:26.500 [强行插入96] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入96 running...
21:36:26.500 [强行插入97] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入97 running...
21:36:26.501 [强行插入98] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入98 running...
21:36:26.501 [强行插入99] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入99 running...---------
非公平锁
21:35:25.239 [t0] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t0 running...
21:35:25.258 [t1] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t1 running...
21:35:25.268 [t2] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t2 running...
21:35:25.279 [t3] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t3 running...
21:35:25.290 [t4] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t4 running...
21:35:25.301 [t5] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t5 running...
21:35:25.312 [t6] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t6 running...
21:35:25.323 [t7] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t7 running...
21:35:25.335 [t8] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t8 running...
21:35:25.345 [t9] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t9 running...
21:35:25.356 [t10] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t10 running...
21:35:25.369 [t11] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t11 running...
21:35:25.382 [t12] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t12 running...
21:35:25.393 [t13] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t13 running...
21:35:25.406 [t14] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t14 running...
21:35:25.416 [t15] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t15 running...
21:35:25.429 [t16] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t16 running...
21:35:25.441 [t17] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t17 running...
21:35:25.453 [t18] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t18 running...
21:35:25.467 [t19] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t19 running...
21:35:25.481 [t20] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t20 running...
21:35:25.492 [t21] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t21 running...
21:35:25.503 [t22] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t22 running...
21:35:25.515 [t23] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t23 running...
21:35:25.526 [t24] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t24 running...
21:35:25.538 [t25] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t25 running...
21:35:25.548 [t26] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t26 running...
21:35:25.561 [t27] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t27 running...
21:35:25.573 [t28] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t28 running...
21:35:25.583 [t29] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t29 running...
21:35:25.596 [t30] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t30 running...
21:35:25.608 [t31] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t31 running...
21:35:25.620 [t32] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t32 running...
21:35:25.631 [t33] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t33 running...
21:35:25.643 [t34] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t34 running...
21:35:25.654 [t35] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t35 running...
21:35:25.667 [t36] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t36 running...
21:35:25.693 [t37] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t37 running...
21:35:25.712 [t38] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t38 running...
21:35:25.725 [t39] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t39 running...
21:35:25.737 [t40] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t40 running...
21:35:25.749 [t41] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t41 running...
21:35:25.773 [t42] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t42 running...
21:35:25.785 [t43] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t43 running...
21:35:25.795 [t44] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t44 running...
21:35:25.806 [t45] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t45 running...
21:35:25.817 [t46] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t46 running...
21:35:25.828 [t47] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t47 running...
21:35:25.839 [t48] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t48 running...
21:35:25.850 [t49] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t49 running...
21:35:25.861 [t50] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t50 running...
21:35:25.874 [t51] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t51 running...
21:35:25.885 [t52] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t52 running...
21:35:25.898 [t53] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t53 running...
21:35:25.911 [t54] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t54 running...
21:35:25.923 [t55] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t55 running...
21:35:25.936 [t56] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t56 running...
21:35:25.948 [t57] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t57 running...
21:35:25.961 [t58] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t58 running...
21:35:25.975 [t59] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t59 running...
21:35:25.989 [t60] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t60 running...
21:35:26.001 [t61] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t61 running...
21:35:26.013 [t62] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t62 running...
21:35:26.025 [t63] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t63 running...
21:35:26.038 [t64] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t64 running...
21:35:26.050 [t65] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t65 running...
21:35:26.062 [t66] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t66 running...
21:35:26.073 [t67] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t67 running...
21:35:26.085 [t68] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t68 running...
21:35:26.101 [t69] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t69 running...
21:35:26.114 [t70] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t70 running...
21:35:26.125 [t71] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t71 running...
21:35:26.138 [t72] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t72 running...
21:35:26.150 [t73] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t73 running...
21:35:26.164 [t74] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t74 running...
21:35:26.175 [t75] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t75 running...
21:35:26.189 [t76] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t76 running...
21:35:26.200 [t77] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t77 running...
21:35:26.211 [t78] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t78 running...
21:35:26.223 [t79] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t79 running...
21:35:26.237 [t80] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t80 running...
21:35:26.249 [t81] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t81 running...
21:35:26.261 [t82] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t82 running...
21:35:26.261 [强行插入50] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入50 running...
21:35:26.263 [强行插入52] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入52 running...
21:35:26.263 [强行插入53] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入53 running...
21:35:26.271 [强行插入54] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入54 running...
21:35:26.272 [强行插入55] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入55 running...
21:35:26.285 [t83] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t83 running...
21:35:26.286 [强行插入73] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入73 running...
21:35:26.293 [强行插入74] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入74 running...
21:35:26.301 [强行插入75] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入75 running...
21:35:26.312 [强行插入76] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入76 running...
21:35:26.321 [强行插入77] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入77 running...
21:35:26.328 [强行插入78] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入78 running...
21:35:26.330 [强行插入79] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入79 running...
21:35:26.336 [强行插入80] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入80 running...
21:35:26.341 [强行插入81] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入81 running...
21:35:26.342 [强行插入83] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入83 running...
21:35:26.359 [强行插入84] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入84 running...
21:35:26.359 [强行插入85] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入85 running...
21:35:26.370 [t84] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t84 running...
21:35:26.381 [t85] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t85 running...
21:35:26.393 [t86] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t86 running...
21:35:26.405 [t87] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t87 running...
21:35:26.416 [t88] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t88 running...
21:35:26.427 [t89] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t89 running...
21:35:26.438 [t90] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t90 running...
21:35:26.449 [t91] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t91 running...
21:35:26.462 [t92] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t92 running...
21:35:26.475 [t93] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t93 running...
21:35:26.486 [t94] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t94 running...
21:35:26.497 [t95] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t95 running...
21:35:26.508 [t96] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t96 running...
21:35:26.520 [t97] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t97 running...
21:35:26.540 [t98] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t98 running...
21:35:26.552 [t99] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - t99 running...
21:35:26.553 [强行插入0] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入0 running...
21:35:26.555 [强行插入1] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入1 running...
21:35:26.556 [强行插入2] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入2 running...
21:35:26.556 [强行插入3] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入3 running...
21:35:26.556 [强行插入4] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入4 running...
21:35:26.557 [强行插入5] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入5 running...
21:35:26.557 [强行插入6] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入6 running...
21:35:26.558 [强行插入7] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入7 running...
21:35:26.558 [强行插入8] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入8 running...
21:35:26.558 [强行插入9] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入9 running...
21:35:26.559 [强行插入10] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入10 running...
21:35:26.559 [强行插入11] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入11 running...
21:35:26.559 [强行插入12] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入12 running...
21:35:26.560 [强行插入13] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入13 running...
21:35:26.560 [强行插入14] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入14 running...
21:35:26.560 [强行插入15] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入15 running...
21:35:26.560 [强行插入16] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入16 running...
21:35:26.560 [强行插入17] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入17 running...
21:35:26.561 [强行插入18] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入18 running...
21:35:26.561 [强行插入19] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入19 running...
21:35:26.561 [强行插入20] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入20 running...
21:35:26.561 [强行插入21] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入21 running...
21:35:26.562 [强行插入22] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入22 running...
21:35:26.562 [强行插入23] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入23 running...
21:35:26.562 [强行插入24] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入24 running...
21:35:26.562 [强行插入25] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入25 running...
21:35:26.562 [强行插入26] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入26 running...
21:35:26.562 [强行插入27] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入27 running...
21:35:26.563 [强行插入28] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入28 running...
21:35:26.563 [强行插入29] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入29 running...
21:35:26.563 [强行插入30] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入30 running...
21:35:26.563 [强行插入31] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入31 running...
21:35:26.563 [强行插入32] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入32 running...
21:35:26.563 [强行插入33] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入33 running...
21:35:26.564 [强行插入34] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入34 running...
21:35:26.564 [强行插入35] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入35 running...
21:35:26.564 [强行插入36] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入36 running...
21:35:26.564 [强行插入37] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入37 running...
21:35:26.564 [强行插入38] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入38 running...
21:35:26.565 [强行插入39] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入39 running...
21:35:26.565 [强行插入40] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入40 running...
21:35:26.565 [强行插入41] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入41 running...
21:35:26.565 [强行插入42] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入42 running...
21:35:26.565 [强行插入43] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入43 running...
21:35:26.566 [强行插入44] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入44 running...
21:35:26.567 [强行插入45] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入45 running...
21:35:26.568 [强行插入46] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入46 running...
21:35:26.568 [强行插入47] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入47 running...
21:35:26.568 [强行插入48] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入48 running...
21:35:26.568 [强行插入49] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入49 running...
21:35:26.568 [强行插入51] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入51 running...
21:35:26.569 [强行插入56] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入56 running...
21:35:26.569 [强行插入57] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入57 running...
21:35:26.569 [强行插入58] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入58 running...
21:35:26.569 [强行插入59] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入59 running...
21:35:26.570 [强行插入60] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入60 running...
21:35:26.570 [强行插入61] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入61 running...
21:35:26.571 [强行插入62] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入62 running...
21:35:26.571 [强行插入63] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入63 running...
21:35:26.571 [强行插入64] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入64 running...
21:35:26.572 [强行插入65] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入65 running...
21:35:26.572 [强行插入66] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入66 running...
21:35:26.575 [强行插入67] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入67 running...
21:35:26.576 [强行插入68] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入68 running...
21:35:26.576 [强行插入69] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入69 running...
21:35:26.576 [强行插入70] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入70 running...
21:35:26.576 [强行插入71] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入71 running...
21:35:26.576 [强行插入72] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入72 running...
21:35:26.576 [强行插入82] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入82 running...
21:35:26.576 [强行插入86] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入86 running...
21:35:26.576 [强行插入87] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入87 running...
21:35:26.577 [强行插入88] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入88 running...
21:35:26.577 [强行插入89] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入89 running...
21:35:26.577 [强行插入90] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入90 running...
21:35:26.577 [强行插入91] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入91 running...
21:35:26.577 [强行插入92] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入92 running...
21:35:26.577 [强行插入93] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入93 running...
21:35:26.577 [强行插入94] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入94 running...
21:35:26.577 [强行插入95] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入95 running...
21:35:26.577 [强行插入96] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入96 running...
21:35:26.578 [强行插入97] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入97 running...
21:35:26.578 [强行插入98] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入98 running...
21:35:26.578 [强行插入99] DEBUG com.sonny.classexercise.concurrent.lock.ReentrantLockDemo5 - 强行插入99 running...

ReentrantLock 的构造函数中,默认的无参构造函数将会把 Sync 对象创建为 NonfairSync 对象,这是一个“非公平锁”;而另一个构造函数 ReentrantLock(boolean fair)传入参数为 true 时将会把 Sync 对象创建为“公平锁” FairSync。

nonfairTryAcquire(int acquires)方法,对于非公平锁,只要 CAS 设置同步状态成功,则表示当前线程获取了锁,而公平锁则不同。tryAcquire 方法,该方法与 nonfairTryAcquire(int acquires)比较,唯一不同的位置为判断条件多了 hasQueuedPredecessors()方法,即加入了同步队列中当前节点是否有前驱节点的判断,如果该方法返回 true,则表示有线程比当前线程更早地请求获取锁,因此需要等待前驱线程获取并释放锁之后才能继续获取锁。

二、原理解析

1 MESA模型

Monitor管程:又称为监视器,它是描述并实现对共享变量的管理与操作,使其在多线程下能正确执行的一个管理策略。可以理解成临界区资源的管理策略。MESA模型是管程的一种实现策略,Java使用的就是该策略。

相关术语

  • enterQueue:管程的入口队列,当线程在申请进入管程中发现管程已被占用,那么就会进入该队列并阻塞。
  • varQueue:条件变量等待队列,在线程执行过程中(已进入管程),条件变量不符合要求,线程被阻塞时会进入该队列。
  • condition variables:条件变量,存在于管程中,一般由程序赋予意义,程序通过判断条件变量执行阻塞或唤醒操作。
    阻塞和唤醒:wait()和await()就是阻塞操作。notify()和notifyAll()就是唤醒操作。

执行流程

  1. 多个线程进入入口等待队列enterQueue,JVM会保证只有一个线程能进入管程内部,Synchronized中进入管程的线程随机。
  2. 进入管程后通过条件变量判断当前线程是否能执行操作,如果不能跳到step3,否则跳到step4。
  3. 条件变量调用阻塞方法,将当前线程放入varQueue,等待其他线程唤醒,跳回step1。
  4. 执行相应操作,执行完毕后调用notify/notifyAll等唤醒操作,唤醒对应varQueue中的一个或多个等待线程。
  5. 被唤醒的线程会从varQueue放入enterQueue中,再次执行step1。
  6. 被唤醒的线程不会立即执行,会被放入enterQueue,等待JVM下一次选择运行,而正在运行的线程会继续执行,直到程序执行完毕。

2 LockSupport

LockSupport 定义了一组的公共静态方法,这些方法提供了最基本的线程阻 塞和唤醒功能,而 LockSupport 也成为构建同步组件的基础工具。

LockSupport 定义了一组以 park 开头的方法用来阻塞当前线程,以及 unpark(Thread thread)方法来唤醒一个被阻塞的线程。LockSupport 增加了 park(Object blocker)、parkNanos(Object blocker,long nanos)和 parkUntil(Object blocker,long deadline)3 个方法,用于实现阻塞当前线程的功能,其中参数 blocker 是用来标识当前线程在等待的对象(以下称为阻塞对象),该对象主要用于问题排查和系统监控。

3 CLH 队列锁

当一个线程需要获取锁时:

  1. 创建一个的QNode,将其中的locked设置为true表示需要获取锁,myPred 表示对其前驱结点的引用

  2. 线程 A 对 tail 域调用 getAndSet 方法,使自己成为队列的尾部,同时获取
    一个指向其前驱结点的引用 myPred

    线程 B 需要获得锁,同样的流程再来一遍

  3. 线程就在前驱结点的 locked 字段上旋转,直到前驱结点释放锁(前驱节点 的锁值 locked == false)

  4. .当一个线程需要释放锁时,将当前结点的 locked 域设置为 false,同时回收 前驱结点如上图所示,前驱结点释放锁,线程 A 的 myPred 所指向的前驱结点的 locked 字段变为 false,线程 A 就可以获取到锁。 CLH 队列锁的优点是空间复杂度低(如果有 n 个线程,L 个锁,每个线程每 次只获取一个锁,那么需要的存储空间是 O(L+n),n 个线程有 n 个 myNode, L 个锁有 L 个 tail)。CLH 队列锁常用在 SMP 体系结构下。 Java 中的 AQS 是 CLH 队列锁的一种变体实现。

ReentrantLock使用及其原理解析相关推荐

  1. ReentrantLock的实现原理

    ReentrantLock 简介 ReentrantLock 实现了 Lock 接口,是一种可重入的独占锁. 相比于 synchronized 同步锁,ReentrantLock 更加灵活,拥有更加强 ...

  2. 详解ReentrantLock之Condition原理

    Condition Jdk中独占锁的实现除了使用关键字synchronized外,还可以使用ReentrantLock.虽然在性能上ReentrantLock和synchronized没有什么区别,但 ...

  3. Spark Shuffle原理解析

    Spark Shuffle原理解析 一:到底什么是Shuffle? Shuffle中文翻译为"洗牌",需要Shuffle的关键性原因是某种具有共同特征的数据需要最终汇聚到一个计算节 ...

  4. 秋色园QBlog技术原理解析:性能优化篇:用户和文章计数器方案(十七)

    2019独角兽企业重金招聘Python工程师标准>>> 上节概要: 上节 秋色园QBlog技术原理解析:性能优化篇:access的并发极限及分库分散并发方案(十六)  中, 介绍了 ...

  5. Tomcat 架构原理解析到架构设计借鉴

    ‍ 点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 Tomcat 架构原理解析到架构设计借鉴 Tomcat 发展这 ...

  6. 秋色园QBlog技术原理解析:性能优化篇:数据库文章表分表及分库减压方案(十五)...

    文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色 ...

  7. CSS实现元素居中原理解析

    原文:CSS实现元素居中原理解析 在 CSS 中要设置元素水平垂直居中是一个非常常见的需求了.但就是这样一个从理论上来看似乎实现起来极其简单的,在实践中,它往往难住了很多人. 让元素水平居中相对比较简 ...

  8. 秋色园QBlog技术原理解析:Web之页面处理-内容填充(八)

    文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色 ...

  9. 秋色园QBlog技术原理解析:UrlRewrite之无后缀URL原理(三)

    文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 本节,将从 ...

  10. Android之Butterknife原理解析

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! ##前言 Butterknife是一个专注于Android系统的View注入框架, ...

最新文章

  1. Tomcat内存溢出解决方法
  2. [译]Web Inspector开始支持CSS区域
  3. linux 安装python MySQLdb
  4. JAVA程序猿面试题汇总
  5. Metal之渲染绘制三角形
  6. 10个我最喜欢问程序员的面试问题
  7. 北大“四大疯人院”之说
  8. IE6/7兼容问题:巧用label去除submit按钮的黑框线
  9. 【bzoj1911-[Apio2010]特别行动队】斜率优化
  10. Java设计模式学习总结(7)——结构型模式之适配器模式
  11. 使用Tftpd64收集交换机日志
  12. 如何用手机远程协助长辈?我找出了6个最佳方法!(免ROOT)
  13. ccboot最新服务器配置,使用CCBoot如何优化服务器和客户端网卡
  14. word在试图打开文件时遇到错误,解决办法
  15. 对象存储(云存储)概述
  16. 将【axmol】引擎的OpenAL实现在iOS平台替换openal-soft详细过程
  17. 史上最全2019届秋招备战攻略
  18. All In One - 第7章 安全运营
  19. 【基础】(C语言)高精度算法
  20. eclipse 取消xml校验

热门文章

  1. python 类的执行中保部存值_python 生成有效的四要素
  2. 图片灯箱插件-lightBox
  3. 建站手册-网站构建:万维网联盟(World Wide Web Consortium)
  4. advGAN代码笔记
  5. 2020年测试面试经历以及面试题大全
  6. 【Java学习笔记】常用API(String、ArrayList)
  7. html如何制作艺术字体,PS制作个性的艺术字特效
  8. 冲向2021 荣耀“无限”创新
  9. 动态规则最佳入门(转)
  10. 系统分析员应具备的能力