死锁

一、死锁产生条件

  1. 互斥条件:一个线程只能被一个线程使用。
  2. 请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持一致不变
  3. 不剥夺条件:线程已获得的资源,在未使用完之前,不强行剥夺。
  4. 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

典型的三种死锁类型:1.静态的顺序死锁;2.动态的顺序死锁;3.协作对象之间发生的死锁。

二、静态的顺序死锁

一下是错误写法例子,可能造成顺序死锁

   public static void main(String[] args) {
        StaticLockOrderDeadLock lock = new StaticLockOrderDeadLock();
        while (true){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    lock.a();
                    lock.c();
                }
            }).start();
        }

    }

class StaticLockOrderDeadLock {
	private final Object lockA = new Object();
	private final Object lockB = new Object();
	public void a() {
		synchronized (lockA) {
			synchronized (lockB) {
				System.out.println("function a");
			}
		}
	}
	public void b() {
		synchronized (lockB) {
			synchronized (lockA) {
				System.out.println("function b");
			}
		}
	}
}

所有需要多个锁的线程,都需要以相同顺序来获得锁。

以下是正确写法例子

public class DeadLock {
    public static void main(String[] args) {
        StaticLockOrderDeadLock lock = new StaticLockOrderDeadLock();
        while (true){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    lock.a();
                    lock.b();
                }
            }).start();
        }

    }
}

 class StaticLockOrderDeadLock {
    private final Object lockA = new Object();
    private final Object lockB = new Object();

    public void a() {
        synchronized (lockA) {
            synchronized (lockB) {
                System.out.println("function a");
            }
        }
    }
     public void c() {
         synchronized (lockB) {
             synchronized ( lockA) {
                 System.out.println("function c");
             }
         }
     }
    public void b() {
        synchronized (lockA) {
            synchronized (lockB) {
                System.out.println("function b");
            }
        }
    }
}

三、动态的顺序死锁

动态的锁顺序死锁是指两个线程调用同一个方法时,传入的参数调到造成的死锁。


  new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lock.transefMoney(new Account(100), new Account(200), 200);
                } catch (InsufficientResourcesException e) {
                    e.printStackTrace();
                }
            }
        }).start();

public void transefMoney(Account fromAccount, Account toAccount, double amount) throws InsufficientResourcesException {
        synchronized (fromAccount) {
            synchronized (toAccount) {
                if (fromAccount.compareTo(amount) < 0) {
                    throw new InsufficientResourcesException();
                } else {
                    toAccount.debit(amount);
                    fromAccount.credit(amount);
                }
            }
        }
    }

输出结果:

javax.naming.InsufficientResourcesException
	at DynamicLockOrderDeadLock.transefMoney(DeadLock.java:35)
	at DeadLock$1.run(DeadLock.java:15)
	at java.lang.Thread.run(Thread.java:748)
class Account implements Comparable {
    String userName;
    String password;
    double moneyCount;


    /**
     * 取款
     *
     * @param amount
     */
    public void debit(double amount) {
        moneyCount -= amount;
        System.out.println(moneyCount);
    }

    public void credit(double amount) {
        moneyCount += amount;
        System.out.println(moneyCount);
    }

    @Override
    public int compareTo(Object o) {
        return (int) (moneyCount - ((double) o));
    }
}

动态死锁解决方法:使用Sysem.identifyHashCode来定义锁的顺序

    new Thread(new Runnable() {
            @Override
            public void run() {
                Account fromAccount = new Account();
                lock.transferMoney2(fromAccount, fromAccount, 200);
            }
        }).start();
        
 public void transferMoney2(Account fromAccount, Account toAccount, double amount) {
        class Helper {
            public void transfer() {
                fromAccount.debit(amount);
                toAccount.credit(amount);
            }
        }
        int fromHash = System.identityHashCode(fromAccount);
        int toHash = System.identityHashCode(toAccount);
        if (fromHash < toHash) {
            synchronized (fromAccount) {
                synchronized (toAccount) {
                    new Helper().transfer();
                }
            }
        } else if (fromHash > toHash) {
            synchronized (toAccount) {
                synchronized (fromAccount) {
                    new Helper().transfer();
                }
            }
        } else {
            synchronized (obj){
                synchronized (fromAccount){
                    synchronized (toAccount){
                        new Helper().transfer();
                    }
                }
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值