Java 多线程 -- 理解锁:手动实现可重入锁和不可重入锁

JDK提供的大多数内置锁都是可重入的,也就是 说,如果某个线程试图获取一个已经由它自己持有的锁时,那么这个请求会立 刻成功,并且会将这个锁的计数值加1,而当线程退出同步代码块时,计数器 将会递减,当计数值等于0时,锁释放。如果没有可重入锁的支持,在第二次 企图获得锁时将会进入死锁状态。
现实中,我们一般不会去手动实现锁,而是直接使用JDK或其他框架提供的锁,手动实现主要为了理解。

不可重入锁:

// 不可重入锁
class Lock{
	// 是否占用
	private boolean isLocked = false;
	// 使用锁
	public synchronized void lock() throws InterruptedException {
		while(isLocked) {
			wait();
		}
		isLocked  = true;
	}
	// 释放锁
	public synchronized void unlock(){
		isLocked = false;
		this.notify();
	}
}

测试:
public class LockTest {
Lock lock = new Lock();
public void a() throws InterruptedException {
lock.lock();
b();
lock.unlock();
}
public void b() throws InterruptedException {
lock.lock();
// …业务代码
lock.unlock();
}

public static void main(String[] args) throws InterruptedException {
	LockTest test = new LockTest();
	test.a();
}

}

运行代码会发现出现死锁
在这里插入图片描述

可重入锁:

// 可重入锁
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) {
			this.wait();
		}
		isLocked = true;
		lockedBy = t;
		holdCount++;
	}
	
	// 释放锁
	public synchronized void unlock() {
		if(Thread.currentThread() == lockedBy) {
			holdCount--;
			if(holdCount == 0) {
				isLocked = false;
				this.notify();
				lockedBy = null;
			}
		}
	}

	public int getHoldCount() {
		return holdCount;
	}

}

测试:

public class LockTest02 {
	ReLock lock = new ReLock();
	public void a() throws InterruptedException {
		lock.lock();
		System.out.println(lock.getHoldCount());
		b();
		lock.unlock();
		System.out.println(lock.getHoldCount());
	}
	public void b() throws InterruptedException {
		lock.lock();
		System.out.println(lock.getHoldCount());
		// .....业务代码
		lock.unlock();
		System.out.println(lock.getHoldCount());
	}
	
	public static void main(String[] args) throws InterruptedException {
		LockTest02 test = new LockTest02();
		test.a();
		Thread.sleep(1000);
		System.out.println(test.lock.getHoldCount());
	}
}

运行代码:
在这里插入图片描述

可重入锁通过计数方式,没有出现死锁现象。

重视基础,才能走的更远。
原文地址:https://www.cnblogs.com/xzlf/p/12681520.html