可重入锁和不可重入锁的的区别及原理

锁:把所需要的代码块,资源,或数据锁上,在操作他们的时候只允许一个线程去做操作

不可重入锁

当A方法获取lock锁去锁住一段需要做原子性操作的B方法时,如果这段B方法又需要锁去做原子性操作,那么A方法就必定要与B方法出现死锁。这种会出现问题的重入一把锁的情况,叫不可重入锁。

A方法需要等B方法执行完才能解锁,但是B方法想执行完代码又必须要lock锁来加锁。A的锁未解锁前,其他代码块无法使用此锁来加锁。这是由这个不可重入锁决定的

例如

public class Test{
     	Lock lock = new Lock();
    	public void methodA(){
         		lock.lock();
         		...........;
         		methodB();
         		...........;
         		lock.unlock();
           	}
        	public void methodB(){
         		lock.lock();
         		...........;
         		lock.unlock();
         	}
}

不可重入锁代码示例

public class Lock{
     	       private boolean isLocked = false;
     	       public synchronized void lock() throws InterruptedException{
         		while(isLocked){    
             		  wait();
         		}
         		isLocked = true;
    	        }
    	        public synchronized void unlock(){
         		isLocked = false;
         		notify();
    	        }
	}

可重入锁

当我们有需要重入一把锁的需求!!!!比如A方法是个原子性操作,但它有需要调用B方法的原子性操作,他们还争抢的是同一个临界资源,因此需要同一把锁来加锁(ps:争抢同一临界资源的实质就是对同一把锁的争抢)

针对此情况,就有了可重入锁的概念,具体实现

public class Lock{
    //锁上的标识
    boolean isLocked = false;
    //临界资源被哪个线程锁住了
    Thread  lockedBy = null;
    //加锁次数
    int lockedCount = 0;
    public synchronized void lock() throws InterruptedException{
        //加锁时,先获取当前线程
        Thread thread = Thread.currentThread();
        //当临界资源已被锁上,但当前请求锁的线程又不是之前锁上临界资源的线程。
        //那么当前请求锁的线程需要等待。
        while(isLocked && lockedBy != thread){
            wait();
        }
        //锁上标识设为true
        isLocked = true;
        //加锁次数+1
        lockedCount++;
        //把自己(本线程)赋值给lockedBy
        //说明当前谁用了这把锁方便之后重入的时候做while判断。
        lockedBy = thread;
    }
    public synchronized void unlock(){
        //检查要求解锁的线程是不是当前用锁的线程。不是则什么也不做
        if(Thread.currentThread() == this.lockedBy){
            //加锁次数-1
            lockedCount--;
            if(lockedCount == 0){
                //变为0说明,这个锁已经完全解锁了。锁上标识islocked可以复位了。
                //并且随机唤醒某个被wait()等待的线程:notify()
                isLocked = false;
                notify();
            }
        }
    }
}

不可重入锁和可重入锁的区别

不可重入锁:只判断这个锁有没有被锁上,只要被锁上申请锁的线程都会被要求等待。实现简单
可重入锁:不仅判断锁有没有被锁上,还会判断锁是谁锁上的,当就是自己锁上的时候,那么他依旧可以再次访问临界资源,并把加锁次数加一。
设计了加锁次数,以在解锁的时候,可以确保所有加锁的过程都解锁了,其他线程才能访问。
不然没有加锁的参考值,也就不知道什么时候解锁?解锁多少次?才能保证本线程已经访问完临界资源了可以唤醒其他线程访问了。实现相对复杂。

总结:这个重入的概念就是,拿到锁的代码能不能多次以不同的方式访问临界资源而不出现死锁等相关问题。
经典之处在于判断了需要使用锁的线程是否为加锁的线程。如果是,则拥有重入的能力


用于个人学习记录

转载自

对可重入锁和不可重入锁的理解,他们的区别及实现原理解析。_Anakki的博客-CSDN博客_重入锁和不可重入锁

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值