Java锁:可重入锁(递归锁)

22 篇文章 0 订阅
4 篇文章 0 订阅
可重入锁
也叫递归锁:递归传递同一把锁
理解:

同一个线程在进入外层同步方法获得锁之后,同样可以进入该外层同步方法中所拥有的内层同步方法,它们此时所拥有的是同一把锁
这种设计可以避免死锁(如果不是可重入锁,在进入外层同步方法之后,无法进入该外层同步方法所拥有的内层同步方法,这种情况下就会出现死锁)

synchronized/ReentrantLock都是可重入锁
代码示例和解释:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 可重入锁:synchronized/ReentrantLock都是可重入锁
 * 可重入锁(也叫递归锁:递归传递同一把锁)
 * 同一个线程在进入外层同步方法获得锁之后,同样可以进入该外层同步方法中所拥有的内层同步方法,它们此时所拥有的是同一把锁
 * 这种设计可以避免死锁(如果不是可重入锁,在进入外层同步方法之后,无法进入该外层同步方法所拥有的内层同步方法,这种情况下就会出现死锁)
 */
public class LockTest {

	public static void main(String[] args){
		
		//创建一个资源类对象实例
		LockResource lockResource = new LockResource();
		
		Runnable runnable = new Runnable() {	
			@Override
			public void run() {
				//运行外层同步方法
				lockResource.sendPhoneMsg();
			}
		};
		
        new Thread(runnable,"t1").start();
        new Thread(runnable,"t2").start();
        
        //让main线程暂停1秒,保证前两个线程已经运行完,再验证ReentrantLock
        try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
        System.out.println();
        System.out.println();
        
        new Thread(lockResource,"t3").start();
        new Thread(lockResource,"t4").start();
		
	}
	
}

//资源类
class LockResource implements Runnable{
	//1)验证synchronized为可重入锁
	//外层同步方法
	public synchronized void sendPhoneMsg(){
		System.out.println(Thread.currentThread().getName()+"---send Phone Msg...");
		//内层同步方法
		sendEmailMsg();
	}
	
	public synchronized void sendEmailMsg(){
		System.out.println(Thread.currentThread().getName()+"---send Email Msg...");
	}
	
	//2)验证ReetrantLock为可重入锁
	//创建一个ReentrantLock锁实例
	Lock lock = new ReentrantLock();
	
	//实现Runnable接口
	@Override
	public void run() {
		//运行进入外层同步方法
		sendPhone();
	}
	
	//外层同步方法
	public void sendPhone(){
		//加锁
		lock.lock();
		try{
			System.out.println(Thread.currentThread().getName()+"---ReentrantLock Test send Phone Msg...");
			//内层同步方法
			sendEmail();
		}finally{
			//释放锁资源
			lock.unlock();
		}
	}
	
	public void sendEmail(){
		//加锁
		lock.lock();
		try{
			System.out.println(Thread.currentThread().getName()+"---ReentrantLock Test send Email Msg...");
		}finally{
			//释放锁资源
			lock.unlock();
		}
	}
}

运行结果:

在这里插入图片描述
证明了:同一个线程在进入外层同步方法获得锁之后,同样可以进入该外层同步方法中所拥有的内层同步方法,这就是可重用锁

思考两个问题:

关于ReentrantLock的.lock()与.unlock()
在这里插入图片描述
问题:这里多个.lock()和.unlock()会编译报错,还是运行报错?
运行结果证明,只要是.lock()和.unlock()成对出现的,不管多少个,都可以编译通过并运行通过
在这里插入图片描述
这种情况不是成对出现的,编译器并没有编译报错可以运行,但是会造成死锁
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值