zl程序教程

您现在的位置是:首页 >  其它

当前栏目

6-死锁

死锁
2023-06-13 09:14:07 时间

死锁

死锁代表的是一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期阻塞,因此程序不可能正常终止(例如:客户一方占用资金等待货物资源,经销商一方占用货物资源等待资金,双方都占用一种资源,并且都在等待一种资源,这就导致交易流程无法正常进行,也就形成了所谓的“死锁”)

死锁产生的四个必要条件:

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

当上述的四个条件都满足时,便形成死锁,当然,死锁的情况下如果打破上述任何一个条件,便可以让死锁消失。开发中应该尽量避免死锁

死锁在代码形式上通常需要锁的嵌套,也就是在锁的内部还有锁

代码实现:必然死锁的案例

package ThreadPool;


//必然死锁案例
public class ThreadDead  {
    // 定义两个资源对象
    public static Object resource1=new Object();
    public static Object resource2=new Object();

    public static void main(String[] args) {
        //定义两个线程

        //线程1
        new Thread(new Runnable() {
            @Override
            public void run() {
                //上锁,第一次线程1锁住资源1
                synchronized (resource1){
                    System.out.println("线程1占用资源1,请求资源2");
                    /*
                    休眠1s,这是为了保证死锁必然发生
                    以计算机的运行速度,保证了休眠1s的情况下,必然会执行线程2
                    此时资源1已经被上锁,待线程2开始运行,第一步就会讲资源2上锁
                    此时两个资源已经都被上锁
                    待两个线程休眠结束,开始运行
                    线程1进入锁阻塞状态,因为资源2已经被锁
                    线程2也进入锁阻塞状态,因为资源1已经被锁
                    两个线程都进入锁阻塞状态,无法正常结束,形成死锁
                     */
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //上锁,第二次线程1锁住资源2
                    synchronized (resource2){
                        System.out.println("线程1成功占用资源2");
                    }
                }
            }
        }).start();

        //线程2
        new Thread(new Runnable() {
            @Override
            public void run() {
                //上锁
                synchronized (resource2){
                    System.out.println("线程2占用资源2,请求资源1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //上锁
                    synchronized (resource1){
                        System.out.println("线程2成功占用资源1");
                    }
                }
            }
        }).start();
    }
}

运行结果

线程1占用资源1,请求资源2
线程2占用资源2,请求资源1

程序仍在运行,且永远不会自行停止,这就形成了死锁