不可重入锁示例(​​同一个线程不可以重入上锁后的代码段​​)

如下是一个不可重入锁的逻辑过程,会发现执行main方法控制台会打印​​执行doJob方法前​​​,然后就会一直线程阻塞,不会打印​​执行doJob方法过程中​​​,原因在于第一次上锁后,由于没有释放锁,因此执行第一次lock后​​isLocked = true​​​,这个时候调用​​doJob()​​​内部又一次调用了​​lock()​​​由于上个线程将​​isLocked = true​​​,导致再次进入的时候就进入死循环。导致线程无法执行​​System.out.println("执行doJob方法过程中");​​​这行代码,因此控制台只能打印​​执行doJob方法前​​。这种现象就造成了不可重入锁

public class Count{
MyLock lock = new MyLock();

public static void main(String[] args) throws InterruptedException {
new Count().doSomeThing(); // 示例的main方法
}
public void doSomeThing() throws InterruptedException {
lock.lock(); // 第一次上锁
System.out.println("执行doJob方法前");
doJob(); // 方法内会再次上锁
lock.unlock(); // 释放第一次上的锁
}
public void doJob() throws InterruptedException {
lock.lock();
System.out.println("执行doJob方法过程中");
lock.unlock();
}
}

/**
* 自定义锁
*/
class MyLock{
private boolean isLocked = false;
public synchronized void lock() throws InterruptedException{
while(isLocked){
wait();
}
isLocked = true; // 线程第一次进入后就会将器设置为true,第二次进入是就会由于where true进入死循环
}
public synchronized void unlock(){
isLocked = false; // 将这个值设置为false目的是释放锁
notify(); // 接触阻塞
}
}

可重入锁示例(​​同一个线程可以重入上锁的代码段,不同的线程则需要进行阻塞​​)

java的可重入锁有:​​ReentrantLock(显式的可重入锁)​​​、​​synchronized(隐式的可重入锁)​

可重入锁诞生的目的就是防止上面不可重入锁的那种情况,导致同一个线程不可重入上锁代码段。

目的就是让同一个线程可以重新进入上锁代码段。

设计可重入锁的示例代码

public class MyReentrantLock {
boolean isLocked = false; // 默认没有上锁
Thread lockedBy = null; // 记录阻塞线程
int lockedCount = 0; // 上锁次数计数

/**
* 上锁逻辑
*/
public synchronized void lock() throws InterruptedException {
Thread thread = Thread.currentThread();
// 上锁了 并且 如果是同一个线程则放行,否则其它线程需要进入where循环进行等待
while (isLocked && lockedBy != thread) {
wait();
}
isLocked = true; // 第一次进入就进行上锁
lockedCount++; // 上锁次数计数
lockedBy = thread; // 当前阻塞的线程
}

/**
* 释放锁逻辑
*/
public synchronized void unlock() {
if (Thread.currentThread() == this.lockedBy) {
lockedCount--; // 将上锁次数减一
if (lockedCount == 0) {// 当计数为0,说明所有线程都释放了锁
isLocked = false; // 真正的将释放了所有锁
notify();
}
}
}
}