Java线程——线程之间的死锁

一,什么是死锁?

  所谓的死锁是指多个线程因为竞争资源而造成的一种僵局(相互等待),若无外力的作用,这些进程都不能向前推进。

二,死锁产生的条件?

  (1)互斥条件:线程要求对所分配的资源(如打印机)进行排他性控制,既在某一段时间内,资源只能被一个线程所占有。

  (2)不剥夺条件:线程所获得的资源在未使用完前,不能被其他的线程强行夺走,只能由该线程自己释放。

  (3)请求和保持的条件:线程已经保持了一个 资源,但又提出了新的资源请求,而该资源被其他的线程所占用,此时请求进程被阻塞,但对自己的资源也不会释放。

  (4)循环等待条件:存在一种线程资源的循环等待链,链中的每一个线程已获得的资源同时被链中下一个线程所请求。

三,产生死锁的一个例子

package com.itheima.gan;
/**
 * 一个简单的死锁类
 * @author 12428
 * 当DeadLock类的对象flag==1时,(td1)先锁定o1,睡眠500毫秒
 * 在td1睡眠的时候,另一个类对象的flag==0,(td2)线程启动,先锁定o2,睡眠500毫秒
 * 静态属性是类的所有对象所共有的。
 * 在td1睡眠结束的时候需要锁定o2才能继续执行,而此o2已被td2锁定
 * td2 睡眠结束后需要锁定 o1 才能继续执行,而此时 o1 已被 td1 锁定; 
 * td1、td2 相互等待,都需要得到对方锁定的资源才能继续执行,从而死锁。
 *
 */
public class DeadLock implements Runnable{
    
    public int flag=1;
    
    //静态对象是类的所有对象共享的
    private static Object o1=new Object(),o2=new Object();
    
    @Override
    public void run() {
        System.out.println("flag = "+flag);
        
        if(flag==1) {
            synchronized(o1) {
                
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                synchronized (o2) {
                    System.err.println("2");
                }
            }
        }
        
        if(flag==0) {
            synchronized (o2) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                synchronized (o1) {
                    System.out.println("3");
                }
            }
        }
    }

    public static void main(String[] args) {
        DeadLock td1=new DeadLock();
        DeadLock td2=new DeadLock();
        
        td1.flag=1;
        td2.flag=0;
        
        //td1,td2都处于可执行的状态,但虚拟机调用那个线程是未知的
        new Thread(td1).start();
        new Thread(td2).start();
    }
}

 

 

四,处理死锁的方法

(1)加锁的顺序(线程按照一定的顺序来加锁)

package com.itheima.gan;
/*
 * 如何避免死锁
 * 加锁的顺序
 */
public class DeadLock2 {
    public int flag=1;
    //静态对象是类的所有对象共享的 
    private static Object o1=new Object(), o2=new Object();
    
    public void money(int flag) {
        
        this.flag=flag;
        
        if(flag==1) {
            synchronized(o1) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized(o2) {
                    System.out.println("当前线程是"+Thread.currentThread().getName()+
                            " "+" flag的值是 :"+flag);
                }
            }
        }
        
        if(flag==0) {
            synchronized(o2) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized(o1) {
                    System.out.println("当前线程是"+Thread.currentThread().getName()+
                            " "+" flag的值是 :"+flag);
                }
            }
        }
    }
    
    
    public static void main(String[] args) {
        final DeadLock2 td1=new DeadLock2();
        final DeadLock2 td2=new DeadLock2();
        
        td1.flag=1;
        td2.flag=0;
        
        final Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                td1.flag=1;
                td1.money(1);
                
            }
        });
        t1.start();
        
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //核心代码,让线程2在线程1执行完在执行,下面join方法的作用是当前线程放弃cpu的执行权,返回到t1线程执行的地方,直到t1线程执行完,再继续向下执行。
                    t1.join();
                }catch (Exception e) {
                    e.printStackTrace();
                }
                
                td2.flag=0;
                //调用方法
                td2.money(0);
            }
        });
        
        t2.start();
    }
}

 

 

 

posted @ 2019-12-04 16:35  颗就完了  阅读(379)  评论(0编辑  收藏  举报