多线程中的死锁
在前面的分析中,我们知道一个对象可以用Synchronized方法或者其他的加锁形式来防止别的任务在互斥还没有释放的时候就访问这个对象。
试想一下这样的情况:某个任务在等待另一个任务,而后者又在等待别的任务,这样一直下去,知道这个链条的任务又在等待第一个任务释放锁,任务之间的互相等待形成了循环,没有一个任务可以执行下去,最终所有的任务都阻塞,形成了死锁。
下面实例中,给出两个静态的资源,线程1先获取obj1对象,在获取obj2对象;线程2先获取obj2对象,再获取obj1对象
/** * 设计一个简单的死锁。 * 首先明白什么叫死锁:两个线程同时占有一个资源。 * @author Xia * */ public class DreadThread implements Runnable{ //两个静态的资源 public static Object obj1 = new Object(); public static Object obj2 = new Object(); //标志位,flag 等于不同的值时执行不同的代码 public int flag = 1; //1 or 2 public DreadThread(int flag) { this.flag = flag; } @Override public void run() { if(flag == 1) { //如果flag等于1,则该线程先获取obj1,在获取obj2 synchronized (obj1) { System.out.println("flag: " + flag + ", 锁住了资源obj1"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("flag: " + flag + ", 等待获取资源obj2"); synchronized (obj2) { System.out.println("flag: " + flag + ", 获得资源obj2"); } } } else if(flag == 2) { //如果flag等于2,则该线程先获取obj2,再获取obj1 synchronized (obj2) { System.out.println("flag: " + flag + ", 锁住了资源obj2"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("flag: " + flag + ", 等待获取资源obj1"); synchronized (obj1) { System.out.println("flag: " + flag + ", 获得资源obj1"); } } } } }
线程的测试类:
public class DreadThreadTest { public static void main(String[] args) { DreadThread thread1 = new DreadThread(1); DreadThread thread2 = new DreadThread(2); //启动线程1 new Thread(thread1).start(); new Thread(thread2).start(); } }
效果:如图所示,程序一直都无法结束。这就是所谓的死锁。