java并发编程(3)避免活跃性危险

时间:2020-12-05 02:30:02

活跃性危险

一、死锁

  发生:每个人都不愿意放弃自己的锁,确想要别人的锁,这就会导致死锁

   1.锁顺序死锁:如果每个线程以固定的顺序获取锁,那么至少在程序中不会出现锁顺序导致的死锁;

    因为顺序固定如:所有线程:A-B-C 则无问题,如果一个A-B B-A则会发生死锁

  例子1:简单死锁

public class LeftRightDeadlock {
private final Object left = new Object();
private final Object right = new Object(); public void leftRight() {
synchronized (left) { //锁住left
synchronized (right) { //锁住right
doSomething();
}
}
}
//如果一个线程进入上面方法锁住 left,另一个线程进入下面方法锁住right,则会产生互相等待 而死锁
public void rightLeft() {
synchronized (right) { //锁住right
synchronized (left) { //锁住left
doSomethingElse();
}
}
} void doSomething() {
} void doSomethingElse() {
}
}

  例子2:转账死锁

public static void transferMoney(Account fromAccount,Account toAccount,DollarAmount amount)
throws InsufficientFundsException {
//转账 a-b 和 b-a ,如果同时发生,则有可能发生死锁;这种取决于参数的传入;并不是能够完全的判断得到
synchronized (fromAccount) {
synchronized (toAccount) {
if (fromAccount.getBalance().compareTo(amount) < 0)
throw new InsufficientFundsException();
else {
fromAccount.debit(amount);
toAccount.credit(amount);
}
}
}
}

  

  2.资源死锁

    同时获取资源,而资源却相互被锁住,就会产生死锁;

      如:一个应用有两个数据库,刚好两个线程进入两个连接池,两个连接池都满了,则需要相互等待对方释放连接

      线程饥饿死锁:表现为线程池不够,线程池内的线程相互等待(A提交B到单线程池,右提交C到单线程池,但是B要等待C完成才能执行)

  3.活锁

    不会阻塞线程,但是也不能继续执行

    类似于程序不断尝试不断失败,永远无法跳出来