首页 > 代码库 > Java线程 - 死锁(deadlock)

Java线程 - 死锁(deadlock)

一、死锁

死锁是指这样一种状况。当多个线程竞争稀缺资源的时,由于他们相互等待获取对方线程所拥有的资源,大家都无法满足,从而都无法继续执行的情形。

 

P2进程拥有R1资源,但他正请求获取R2资源;而P1进程拥有R2资源,但他正请求R1资源。

 

1.1 Coffman条件--产生死锁的4个条件

如果一个系统中如下4种情形同时存在,则产生死锁情形的机会就会上升

  • 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用
  • 等待和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放
  • 不可剥夺条件进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放
  • 环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链。更一般性来讲会有进程集合{P1,P2,P3....Pn},P1 申请P2获取的资源,P2申请P3资源....而Pn申请P1获取的资源,这样形成了一个闭环。

这4个条件即Coffman条件,由Edward G.Coffman, Jr先生于1971年首次提出。

 

二、java多线程死锁探测

从JDK1.5开始java.lang.management包提供了ThreadMXBean类,该类可用获取关于线程的各种各样的信息,包括探测线程的死锁。findMonitorDeadlockedThreads()方法返回long[],这些long[]表示发生死锁的线程的id。如果long[]数组等于null则表示没有发现死锁的线程。但这个方法只是监控object monitor的死锁,对于使用java.util.concurrent包的ownable synchronizer则无能为力。为此JDK1.6引入了一个新的方法findDeadlockedThreads()除了监控object monitor死锁外,同时还监控ownable synchronizer的死锁。

通过建立一个定期任务,让它使用ThreadMXBean定期核查是否存在死锁的线程,就可以解决线程死锁探测的问题。例如:

public class ThreadDeadlockDetector {        //建立定期任务的调度器    private final Timer threadCheck = new Timer("ThreadDeadLockDector",true);        private final Collection<Listener> listeners = new CopyOnWriteArraySet<Listener>();        private final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();            private static final int DEFAULT_DEADLOCK_CHECK_PERIOD = 10000;        public ThreadDeadlockDetector(){        this(DEFAULT_DEADLOCK_CHECK_PERIOD);    }        public ThreadDeadlockDetector(int deadlockCheckPeriod){        //建立一个定期核查的任务        threadCheck.schedule(new TimerTask(){            @Override            public void run() {                checkForDeadlocks();            }                    }, 10, deadlockCheckPeriod);    }        //一旦返现有死锁,就发出死锁报警    private void checkForDeadlocks() {        long[] ids = findDeadlockedThreads();        if(ids != null && ids.length > 0) {            Thread[] threads = new Thread[ids.length];            for(int i=0; i<threads.length; i++){                threads[i] = findMatchingThread(mbean.getThreadInfo(ids[i]));            }            fireDeadlockDetected(threads);        }            }        //核查是否存在死锁    private long[] findDeadlockedThreads(){        if(mbean.isSynchronizerUsageSupported()){            return mbean.findDeadlockedThreads();        }else{            return mbean.findMonitorDeadlockedThreads();        }    }        private Thread findMatchingThread(ThreadInfo inf){        for(Thread thread:Thread.getAllStackTraces().keySet()){            if(thread.getId() == inf.getThreadId()){                return thread;            }        }                throw new IllegalStateException("Deadlocked Thread not found");    }        public boolean addListener(Listener l){        return listeners.add(l);    }        public boolean removeListener(Listener l){        return listeners.remove(l);    }        private void fireDeadlockDetected(Thread[] threads){        for(Listener l : listeners){            l.deallockDetected(threads);        }    }        public interface Listener {        void deallockDetected(Thread[] deadlockedThreads);    }}

 

Java线程 - 死锁(deadlock)