java并发编程(3)避免活跃性危险
活跃性危险
一、死锁
发生:每个人都不愿意放弃自己的锁,确想要别人的锁,这就会导致死锁
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.活锁
不会阻塞线程,但是也不能继续执行
类似于程序不断尝试不断失败,永远无法跳出来