源码仓库Gitee · GitHub背景什么是 “可重入”可重入就是说某个线程已经获得某个锁可以再次获取锁而不会出现死锁。即可重入锁的作用就是为了避免死锁java中synchronized和ReentrantLock都是可重入锁。//synchronized 可重入锁 private void test() { // 第一次获得锁 synchronized (this) { while (true) { // 第二次获得同样的锁 synchronized (this) { System.out.println(ReentrantLock!); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } //ReentrantLock可重入锁 Lock lock new ReentrantLock(); private void test1() { lock.lock(); try { test2(); } finally { lock.unlock(); } } private void test2() { lock.lock(); try { System.out.println(ReentrantLock!); } finally { lock.unlock(); } }一.自定义不可重入锁所谓不可重入锁即若当前线程执行某个方法已经获取了该锁那么在方法中尝试再次获取锁时就会获取不到被阻塞。下面的线程执行test1()方法首先获取lock接下来执行test2()方法就无法执行test2()中的逻辑必须先释放锁。// 不可重入锁 class Lock { //是否占用 private boolean isLocked false; //使用锁 public synchronized void lock() { while (isLocked) {//已经占用 try { this.wait();//等待 } catch (InterruptedException e) { e.printStackTrace(); } } isLocked true;//修改标识为已经占用 } //释放锁 public synchronized void unLock() { isLocked false;//修改标识为未占用 notify();//唤醒等待线程 } } 使用 Lock lock new Lock(); public void test1() { lock.lock(); test2(); lock.unLock(); } private void test2() { lock.lock(); //... lock.unLock(); }二.自定义可重入锁流程定义锁占用标识、存储线程、线程锁持有数量使用锁判断是否已经占用和当前线程是否不等于存储线程如果条件符合进入等待不符合则修改占用标识、存储线程为当前线程、线程锁数量1释放锁判断当前线程是否等于存储线程条件符合则线程锁数量-1当线程锁数量0时修改占用标识唤醒等待线程将存储线程置为null// 可重入锁 class ReLock{ //是否占用 private boolean isLocked false; private Thread lockedBy null; //存储线程 private int holdCount 0; //使用锁 public synchronized void lock() throws InterruptedException { Thread t Thread.currentThread(); while(isLocked lockedBy ! t) { wait(); } isLocked true; lockedBy t; holdCount ; } //释放锁 public synchronized void unlock() { if(Thread.currentThread() lockedBy) { holdCount --; if(holdCount 0) { isLocked false; notify(); lockedBy null; } } } public int getHoldCount() { return holdCount; } } 使用 public class LockTest { ReLock lock new ReLock(); public void test1() throws InterruptedException { lock.lock(); System.out.println(lock.getHoldCount()); test2(); lock.unlock(); System.out.println(lock.getHoldCount()); } //可重入 public void test2() throws InterruptedException { lock.lock(); System.out.println(lock.getHoldCount()); //................... lock.unlock(); System.out.println(lock.getHoldCount()); } public static void main(String[] args) throws InterruptedException { LockTest lockTest new LockTest(); lockTest.test1(); Thread.sleep(1000); System.out.println(lockTest.lock.getHoldCount()); } }