什么是死锁: 发生在并发中,两者互不相让,互相持有对方所需要的资源,又不主动释放,导致程序卡死。
死锁的影响 死锁的影响在不同的系统中不同的。在数据库中就是可以检测并且放弃事务的。但是JVM无法自动处理死锁。
死锁发生的几率不高但是危害大,压力测试无法找出所有的潜在死锁。
图解Java并发设计认为三点
存在多个资源块线程持有某个资源块时还希望获得其他的资源块获取资源的顺序并不固定。可以采用ThreadMXBean这一工具类。
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); long[] deadlockedThreads = threadMXBean.findDeadlockedThreads(); if (deadlockedThreads != null && deadlockedThreads.length>0){ for (int i = 0; i < deadlockedThreads.length; i++) { ThreadInfo threadInfo = threadMXBean.getThreadInfo(deadlockedThreads[i]); System.out.println("find "+threadInfo.getThreadName()); } }修复策略:
避免策略:哲学家就餐,设置一致的锁的获取顺序。检测与恢复策略:每隔一段时间检测是否有死锁,如果有就剥夺某一个资源,打开死锁。鸵鸟策略:直到发生死锁,再进行修复。参考
public class test { public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); int sum = 5; Chopstick[] chopsticks = new Chopstick[sum]; for (int i = 0; i < sum; i++) { chopsticks[i] = new Chopstick(); } for (int i = 0; i < sum; i++) { exec.execute(new Philosopher(chopsticks[i], chopsticks[(i + 1) % sum])); } } } // 筷子 class Chopstick { public Chopstick() { } } class Philosopher implements Runnable { private Chopstick left; private Chopstick right; public Philosopher(Chopstick left, Chopstick right) { this.left = left; this.right = right; } @Override public void run() { try { while (true) { Thread.sleep(100);//思考一段时间 System.out.println(Thread.currentThread().getName() + " " + "Think"); synchronized (left) { System.out.println(Thread.currentThread().getName() + " " + "left"); synchronized (right) { System.out.println(Thread.currentThread().getName() + " " + "right"); Thread.sleep(1000);//进餐一段时间 } } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }8个经验:
设置超时时间:tryLock(1000,TimeUnit.MILLISECONDS)。synchronized无法尝试锁。获取锁失败再尝试发邮件,报警等。多使用并发类,不要自己设置锁。ConcurrentHashMap,ConcurrentLinkedQueue,AtomicBoolean尽量较低锁的使用粒度和临界区。如果可以使用同步代码块优先使用。给线程起有意义的名字。避免锁的嵌套。分配资源前考虑能不能收回,银行家算法不要几个功能用同一把锁。持有锁之后一段时间放开锁,再重新获得锁。可能正好还是卡死,编程活锁。 活锁的特点是线程没有被阻塞,但是没有进展。活锁还要持续消耗cpu资源。双方相互谦让导致谁都无法持有锁。
引入随机重试,解决活锁问题。线程需要资源但是无法得到资源。 优先级的设置需要注意。