Java多线程(八)——死锁

线程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、调整对多个锁的获取顺序;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值