目录
1.什么是死锁
2.发生死锁的例子
2.1简单的例子
2.2生产中的例子-转账
2.3模拟多人转账
3.死锁的4个必要条件
4.如何定位死锁
5.修复死锁的策略
5.1线上发生死锁怎么办?
5.2常见修复的策略
6.实际工作中如何避免死锁
public class MustDeadLock implements Runnable { int flag = 1; static Object o1 = new Object(); static Object o2 = new Object(); public static void main(String[] args) { MustDeadLock r1 = new MustDeadLock(); MustDeadLock r2 = new MustDeadLock(); r1.flag = 1; r2.flag = 0; new Thread(r1).start(); new Thread(r2).start(); } @Override public void run() { if (flag == 1){ synchronized (o1){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o2){ System.out.println("r1成功拿到两把锁"); } } } if (flag == 0){ synchronized (o2){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o1){ System.out.println("r2成功拿到两把锁"); } } } } }
public class TransferMoney implements Runnable{ int flag = 1; static Account a = new Account(500); static Account b = new Account(500); public static void main(String[] args) throws InterruptedException { TransferMoney r1 = new TransferMoney(); TransferMoney r2 = new TransferMoney(); r1.flag = 1; r2.flag = 0; Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); t1.join(); t1.join(); System.out.println("a的余额"+a.balance); System.out.println("b的余额"+b.balance); } @Override public void run() { if (flag ==1){ transferMoney(a,b,200); } if (flag ==0){ transferMoney(b,a,200); } } public static void transferMoney(Account from, Account to, int amount) { synchronized (from){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (to){ if (from.balance - amount <0){ System.out.println("余额不足,转账失败"); } from.balance-=amount; to.balance+=amount; System.out.println("转账成功"); } } } static class Account{ int balance; public Account(int balance) { this.balance = balance; } } }
public class MultTransferMoney { public static final int NUM_ACCOUNTS = 500; public static final int NUM_MONEY = 1000; public static final int NUM_ITERATIONS = 1000; public static final int NUM_THREADS = 20; public static void main(String[] args) { final Random rnd = new Random(); final Account[] accounts = new Account[NUM_ACCOUNTS]; for (int i = 0; i < accounts.length; i++) { accounts[i] = new Account(NUM_MONEY); } class TransferThread extends Thread{ @Override public void run(){ for (int i = 0; i < NUM_ITERATIONS; i++) { int fromAcct = rnd.nextInt(NUM_ACCOUNTS); int toAcct = rnd.nextInt(NUM_ACCOUNTS); int amount = rnd.nextInt(NUM_MONEY); TransferMoney.transferMoney(accounts[fromAcct],accounts[toAcct],amount); } } } for (int i = 0; i < NUM_THREADS; i++) { new TransferThread().start(); } } }
使用ThreadMaxBean
public class ThreadMXBeanD implements Runnable{ int flag = 1; static Object o1 = new Object(); static Object o2 = new Object(); public static void main(String[] args) { ThreadMXBeanD r1 = new ThreadMXBeanD(); ThreadMXBeanD r2 = new ThreadMXBeanD(); r1.flag = 1; r2.flag = 0; new Thread(r1).start(); new Thread(r2).start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); final long[] deadlockedThreads = threadMXBean.findDeadlockedThreads(); if (deadlockedThreads != null && deadlockedThreads.length > 0){ for (int i = 0; i < deadlockedThreads.length; i++) { final ThreadInfo threadInfo = threadMXBean.getThreadInfo(deadlockedThreads[i]); // 发生死锁Thread-1 // 发生死锁Thread-0 System.out.println("发生死锁"+threadInfo.getThreadName()); } } } @Override public void run() { if (flag == 1){ synchronized (o1){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o2){ System.out.println("r1成功拿到两把锁"); } } } if (flag == 0){ synchronized (o2){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o1){ System.out.println("r2成功拿到两把锁"); } } } } }