Java 可重入锁和不可重入锁理解

什么是可重入锁和不可重入锁?

首先我们从字面意思理解
** 不可重入锁**,要理解可重入锁,我就想是不是有不可重入锁,果然还真有,从字面上理解就是:不可以重新进入锁,资料上的解释就是同一个线程不能够重新获取同一个锁,这似乎也符合我们初步学习锁时的理解,lock()后只有unlock()后其他地方才能调用lock()成功。

按照我们对锁的理解,第n行代码处调用了lock.lock() 方法,其他地方尝试调用lock.lock()都会被阻塞,等待第n行代码的锁被释放

出现的问题

就像下面的代码,如果使用不可重入锁就导致了死锁状态。
第一行获取锁,第三行这一行会等待第一行的锁释放锁,才能获取成功,第一行的锁要运行到第六行才能释放,互相等待,就产生了死锁

	lock.lock();//第一行获取锁
	{
		lock.lock();//第三行,这一行会等待上一行的锁释放锁,才能获取成功,第一行的锁要运行到第六行才能释放
		lock.unlock();//第四行,释放第三行锁	
	}//这是一个代码块,一般是调用别人的方法,我们不能确定别人的方法中有没有申请这个锁
	lock.unlock();//第六行,释放第一行锁

引入可重入锁

** 可重入锁** ,即可以重新进入锁,就是我们获取这一把锁之后,同一个线程尝试获取锁时,可以获取锁成功,这就是可重入锁。

就像下面的代码,如果使用可重入锁就不会出现死锁状态。
第一行获取锁,第三行这一行会判断是同一个线程,同样也可以获取锁,不会等待第一行锁释放,执行成功继续往下执行

	lock.lock();//第一行获取锁
	{
		lock.lock();//第三行,这一行会判断是同一个线程,同样也可以获取锁,不会等待第一行锁释放
		lock.unlock();//第四行,释放第三行锁	
	}//这是一个代码块,一般是调用别人的方法,我们不能确定别人的方法中有没有申请这个锁
	lock.unlock();//第六行,释放第一行锁

Java中几乎所有自带的的锁实现几乎都是可重入锁,当然我们常见的ReentrantLock 和 synchronize就是典型的可重入锁。

实现思路和DEMO代码

不可重入锁

这里只是demo代码,没有实现太多具体细节,成员变量一个isLocked 存储锁状态,lockedBy 存储获取锁的线程用于解锁时使用

	/**
	 * 不可重入锁
	 *
	 */
	public static class UnReLock {
		private volatile  boolean isLocked = false;
		Thread lockedBy = null; //记录当前获取锁线程

		public synchronized void lock() throws InterruptedException {
			Thread thread = Thread.currentThread();
			while (isLocked) {
				wait();
			}
			isLocked = true;
			lockedBy = thread;
		}

		public synchronized void unlock() {
			if (Thread.currentThread() == this.lockedBy) {
				isLocked = false;
				lockedBy = null;
				notify();
			}
		}
	}

可重入锁

首先可重入锁的可重入指的是同一个线程,所以我们需要判断是否是同一个线程尝试获取锁;
其次我们知道可以多次获取锁,不可能unlock()一次就把锁给释放了,所以我们对取锁次数进行计数,当调用lock()时锁计数+1,释放锁时就-1,这样当锁数量为0时就说明所有获取的锁都被释放。
实现代码如下(这里只是demo示例代码,演示思路,没有实现太多具体细节)

	/**
	 * 可重入锁
	 * @author chenlinhui
	 *
	 */
	public static class ReLock {
		volatile boolean  isLocked = false; //记录锁状态
		volatile Thread lockedBy = null; //记录当前获取锁线程
		volatile int lockedCount = 0;    //记录计数器

		public synchronized void lock() throws InterruptedException {
			Thread thread = Thread.currentThread();
			while (isLocked &&( lockedBy != thread)) {
				//已加锁,且不是同一个线程,需要等待
				wait();
			}
			isLocked = true;
			lockedCount++;//锁次数+1
			lockedBy = thread;
		}

		public synchronized void unlock() {
			if (Thread.currentThread() == this.lockedBy) {
				lockedCount--;//锁次数减一
				if (lockedCount == 0) { //锁次数为0,说明所有锁被释放
					isLocked = false;
					lockedBy = null;
					notify();
				}
			}
		}
	}

验证

public class TestUnReLock {
	static ReLock lockObject = new ReLock();  //测试可重入锁
	//static UnReLock lockObject = new UnReLock(); //打开注解测试不可重入锁
	/**
	*我们自己写的方法
	*/
	public static void methodA_1() throws InterruptedException {
		
		lockObject .lock();
		System.out.println("methodA_1,获取锁。。。。");
		methodB_1();//调用别人实现的方法
		lockObject.unlock();
		System.out.println("methodA_1,释放锁成功了");
	}
	/**
	*可能是别人的不可修改的接口或方法
	*/
	public static void methodB_1() throws InterruptedException {
		System.out.println("methodB_1,等待锁。。。。");

		lockObject .lock();
		System.out.println("methodB_1,我获取锁成功了");
		lockObject .unlock();
		System.out.println("methodB_1,释放锁成功了");
	}
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, InterruptedException {
		methodA_1();
		
	}
可重入锁结果,执行成功
methodA_1,获取锁。。。。
methodB_1,等待锁。。。。
methodB_1,我获取锁成功了
methodB_1,释放锁成功了
methodA_1,释放锁成功了
不可重入锁结果:无限等待
methodA_1,获取锁。。。。
methodB_1,等待锁。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huihttp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值