多线程死锁经典案例,必定会发生死锁

        Java线程死锁是一个经典的多线程问题,因为不同的线程都在等待根本不可能被释放的锁,从而导致所有的任务都无法继续完成。换言之只要互相等待对方释放锁就有可能出现死锁。下面将用一个简单的例子加以说明,如有问题,请多多指教。

        某日AB两位壮士各获一张一模一样的藏宝图,他们相距甚远,互不认识。两位壮士不仅武艺双全,还富有谋略,细读藏宝图,壮士得知宝藏就在某处,但是需要两把钥匙才能开启,而这两把钥匙分别存在了某处,恰巧壮士A离钥匙1更近,壮士B离钥匙2更近,于是他们采用就近原则开启寻宝之路。A先找到了钥匙1,为了安全起见,A把钥匙收入囊中,这时B也找到了钥匙2,为了安全起见,B也把钥匙收入囊中。他们各自开始寻找第二把钥匙,但是到达他们原定的目的地之后并没有找到钥匙(其实都被对方据为己有了),但是心有不甘,心想这绝不能半途而废,他们就这样一直在苦苦等待寻找着......

        上面就是多线程死锁的经典案例,两个人可看作是两个不同的线程,A获得了一把锁a想尝试获取另外一把锁b,B获取了一把锁b想尝试获取另外一把锁a,他们互相持有对方想要的锁,在没有获取到对方的锁之前,是不会将自己的锁给放弃的,这样双方永远也无法集齐两把锁,于是发生了死锁。

        下面用代码来实现上面的场景:

public class DeathlyLockService {

	//钥匙一
	private Object lock1 = new Object();
	//钥匙二
	private Object lock2 = new Object();
	
	//开启宝藏之方法,线路不同,先后获取到的钥匙也不同
	public void openTreasure() throws Exception{
		//线路一
		if(Thread.currentThread().getName().equals("大AAA")){
			//先获取的是钥匙一
			synchronized (lock1) {
				System.out.println("线程"+Thread.currentThread().getName()+"拿到了lock1");
				//成功获取到一枚钥匙,继续寻找
				Thread.sleep(2000);
				//尝试获取第二把钥匙
				synchronized(lock2){
					//成功获取到第二把钥匙
					System.out.println("线程"+Thread.currentThread().getName()+"拿到了lock2");
					Thread.sleep(2000);
					//开启了宝藏
					System.out.println("线程"+Thread.currentThread().getName()+"集齐了两把钥匙开宝藏成功");
				}
			}
		}
		//线路二
		if(Thread.currentThread().getName().equals("小BBB")){
			//先获取钥匙二
			synchronized (lock2) {
				System.out.println("线程"+Thread.currentThread().getName()+"拿到了lock2");
				//成功获取到一枚钥匙,继续寻找
				Thread.sleep(2000);
				//尝试获取第二把钥匙
				synchronized(lock1){
					//成功获取到第二把钥匙
					System.out.println("线程"+Thread.currentThread().getName()+"拿到了lock1");
					Thread.sleep(2000);
					//开启了宝藏
					System.out.println("线程"+Thread.currentThread().getName()+"集齐了两把钥匙开宝藏成功");
				}
			}
		}
	}
}
//自定义线程
public class MyThread extends Thread{

	private DeathlyLockService deathlyLockService;
	
	public MyThread(DeathlyLockService deathlyLockService){
		this.deathlyLockService=deathlyLockService;
	}
	
	@Override
	public void run(){
		try {
			System.out.println("线程"+Thread.currentThread().getName()+"开始执行");
			deathlyLockService.openTreasure();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

        main方法测试:

//互相持有对方的锁,比如A对象进行操作时,需要B对象释放锁,此时B对象正在操作,需要A对象释放锁
		DeathlyLockService s = new DeathlyLockService();
		Thread a = new MyThread(s);
		a.setName("大AAA");
		a.start();
		Thread b = new MyThread(s);
		b.setName("小BBB");
		b.start();

打印结果永远卡在:

        线程小BBB开始执行
        线程大AAA开始执行
        线程小BBB拿到了lock2

        线程大AAA拿到了lock1

        。。。。。。

结论:因为发生了死锁,他们俩永远无法获取宝藏。知道了怎样会发生死锁,就知道如何避免这种情况的发生,希望大家以后都能开心的寻宝。


猜你喜欢

转载自blog.csdn.net/yy455363056/article/details/80188381