Java多线程中的死锁

某个线程T1锁住资源A,需要再拿到资源B的锁才能执行完成,而另一个线程T2锁住了资源B,需要再拿到资源A的锁才能完成,但是T2不把资源B的锁给T1,T1线程就无法继续往下执行,T1不把资源A给T2,T2的任务也无法完成,所以就线程相互僵持的现象,这种现象称之为死锁。

代码示例如下:

package com.trs.thread;


/**
 * 死锁示例
 * @author xiayunan
 * @date   2018年7月14日
 *
 */
public class TestDeadLock2 {
	
	public static void main(String[] args) {
		Thread t1 = new Thread(new MyThread5(0));
		Thread t2 = new Thread(new MyThread5(1));
		t1.start();
		t2.start();
	}
	
}

class MyThread5 implements Runnable{
	private static Object o1 = new Object();
	private static Object o2 = new Object();
	private int flag;
	
	public MyThread5(int flag) {
		this.flag = flag;
	}
	@Override
	public void run() {
		if(flag==0){
			synchronized (o1) {
				System.out.println(Thread.currentThread().getName()+"锁住了o1");
				synchronized (o2) {
					System.out.println(Thread.currentThread().getName()+"执行结束");
				}
			}
		}else{
			synchronized (o2) {
				System.out.println(Thread.currentThread().getName()+"锁住了o2");
				synchronized (o1) {
					System.out.println(Thread.currentThread().getName()+"执行结束");
				}
			}
		}
		
	}
	
}

运行结果如下:


从结果中可以看出,程序处于僵持状态,一直没有再继续执行。

那我们应该如何避免死锁呢?

1、加锁顺序(线程按照一定的顺序加锁);

若让上述两个线程都先获取资源o1的锁,死锁情况就不会发生

2、加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁);

加锁时效的原理就是:给每一个访问线程增加访问时效,若一个线程没有在给定的时限内成功获得所有需要的锁,则会进行回退并释放所有已经获得的锁(此时就打破了造成死锁的四个原因中的第三个原因),然后等待一段随机的时间再重试。


猜你喜欢

转载自blog.csdn.net/xyajia/article/details/81040360