Java多线程(八)——死锁

来源:互联网 发布:java 圣思园教程百度云 编辑:程序博客网 时间:2024/05/22 14:26

线程A当前持有互斥所锁lock1,线程B当前持有互斥锁lock2。接下来,当线程A仍然持有lock1时,它试图获取lock2,因为线程B正持有lock2,因此线程A会阻塞等待线程B对lock2的释放。如果此时线程B在持有lock2的时候,也在试图获取lock1,因为线程A正持有lock1,因此线程B会阻塞等待A对lock1的释放。二者都在等待对方所持有锁的释放,而二者却又都没释放自己所持有的锁,这时二者便会一直阻塞下去。这种情形称为死锁。

下列代码演示了死锁:

public class ThreadDeadlock {    public static void main(String[] args) {        Object obj1 = new Object();        Object obj2 = new Object();        Object obj3 = new Object();        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");        Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");        try {            t1.start();            Thread.sleep(1000);            t2.start();            Thread.sleep(1000);            t3.start();        } catch (InterruptedException e) {            System.out.println("失败!");        }        try {            Thread.sleep(15000);            System.out.println("试图中断死锁的线程t1");            t1.interrupt();            System.out.println("试图中断死锁的线程t2");            t2.interrupt();            System.out.println("试图中断死锁的线程t3");            t3.interrupt();        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}class SyncThread implements Runnable {    private Object obj1;    private Object obj2;    public SyncThread(Object o1, Object o2) {        this.obj1 = o1;        this.obj2 = o2;    }    @Override    public void run() {        String name = Thread.currentThread().getName();        System.out.println("线程" + name + " 准备获取" + obj1 + " 的锁 ");        synchronized (obj1) {            System.out.println("线程" + name + " 已经获取" + obj1 + " 的锁 ");            try {                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println("线程" + name + " 准备获取" + obj2 + " 的锁 ");            synchronized (obj2) {                System.out.println("线程" + name + " 已经获取" + obj2 + " 的锁 ");                try {                    Thread.sleep(5000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }}

运行结果如下:

线程t1 准备获取java.lang.Object@1102fab 的锁 线程t1 已经获取java.lang.Object@1102fab 的锁 线程t2 准备获取java.lang.Object@16f5b17 的锁 线程t2 已经获取java.lang.Object@16f5b17 的锁 线程t3 准备获取java.lang.Object@b950d1 的锁 线程t3 已经获取java.lang.Object@b950d1 的锁 线程t1 准备获取java.lang.Object@16f5b17 的锁 线程t2 准备获取java.lang.Object@b950d1 的锁 线程t3 准备获取java.lang.Object@1102fab 的锁 试图中断死锁的线程t1试图中断死锁的线程t2试图中断死锁的线程t3

由于t1,t2,t3三个线程分别持有了obj1 ,obj2,obj3的互斥锁。
接下来需要分别获取obj2,obj3,obj1锁,而该锁已分别被t2,t3,t1线程持有。发生死锁现象,调用Thread.interrupt()方法试图中断线程,却发现线程仍然在继续运行。

避免死锁是一件困难的事,遵循以下原则有助于规避死锁:

1、能够原子性的获取需要的多个锁;

2、调整对多个锁的获取顺序;

1 0