Java死锁

什么是死锁

死锁:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期的阻塞,因此程序不可能正常终止。(两个甚至多个线程被永久阻塞时的一种运行局面,这种局面的生成伴随着至少两个线程和两个或者多个资源。)

死锁的产生条件

  1. 互斥使用:即当资源被一个线程占用(使用)时,别的线程不能使用。
  2. 不可抢占:资源请求者不能强制从资源占有者手中抢夺资源,资源只能等待占有者主动释放。
  3. 请求和保持:即当资源请求者在请求其他资源的同时保持对原有资源的占有。
  4. 循环等待:存在一个等待队列,P1占有p2的资源,p2占有p3的资源,p3占有p1的资源。就这样形成了一个等待环路。

当上述四个条件都成立时,则形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。

死锁的Java实例:

public class DeadLock {
    public static String obj1 = "obj1";
    public static String obj2 = "obj2";

    public static void main(String[] args) {

        LockA lockA = new LockA();
        new Thread(lockA).start();
        LockB lockB = new LockB();
        new Thread(lockB).start();

    }

    static class LockA implements Runnable {
        public void run() {
            try {
                System.out.println(new Date().toString() + " : LockA 开始执行");
                while (true) {
                    synchronized (obj1) {
                        System.out.println(new Date().toString() + " : LockA 锁住了obj1");

                        Thread.sleep(3000);// 获取obj1后先等一会儿,让LockA有足够的时间锁住obj2

                        synchronized (obj2) {
                            System.out.println(new Date().toString() + " : LockA 锁住了obj2");

                            Thread.sleep(60 * 1000);// 为测试,占用了就不放

                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    static class LockB implements Runnable {
        public void run() {
            try {
                System.out.println(new Date().toString() + " : LockB 开始执行");
                while (true) {
                    synchronized (obj2) {
                        System.out.println(new Date().toString() + " : LockB 锁住了obj2");

                        Thread.sleep(3000);// 获取obj2后先等一会儿,让LockB有足够的时间锁住obj1

                        synchronized (obj1) {
                            System.out.println(new Date().toString() + " : LockB 锁住了obj1");

                            Thread.sleep(60 * 1000);// 为测试,占用了就不放

                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}


//结果打印
Wed Nov 01 17:38:00 CST 2017 : LockB 开始执行
Wed Nov 01 17:38:00 CST 2017 : LockB 锁住了obj2
Wed Nov 01 17:38:00 CST 2017 : LockA 开始执行
Wed Nov 01 17:38:00 CST 2017 : LockA 锁住了obj1

信号量(解决死锁)

为了解决这个问题,我们不使用显示的去锁,我们用信号量去控制。
信号量可以控制资源能被多少线程访问,这里我们指定只能被一个线程访问,就做到了类似锁住。而信号量可以指定去获取的超时时间,我们可以根据这个超时时间,去做一个额外处理。
对于无法成功获取的情况,一般就是重复尝试,或指定尝试的次数,也可以马上退出。
详细解决方案参考:Java死锁和解决方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值