死锁只在同步(使用锁定)线程访问一个或多个共享资源(变量和对象)或指令集(关键节)的同时(多线程)程序中发生。
在实时阻止时,如果我们试图避免死锁,在使用异步锁定时会发生。 其中,多个线程与同一组锁定发生冲突的写入操作允许其他线程首先到达的捕获锁定,并在等待最终释放锁定之后继续,以避免获取锁定。 这容易导致CPU周期饥饿,因为等待线程重试获取锁定。 异步锁定只不过是防止死锁变成活动封锁的战略。
以下是从理论上解决死锁的几种方法。 而且,其中之一(第二个)主要原因是原始锁定。
理论方法
1.请勿使用锁定
如果需要同步两个操作,则不可能。 例如,简单的银行转帐可以借记到一个帐户,贷记到另一个帐户。 另外,在当前线程完成之前,不允许其他线程接触账户的余额。
2 .请勿锁定。 如果线程无法获取锁定,则必须释放以前获取的锁定,以便以后可以重试
实施起来很麻烦,可能会导致饥饿(活动阻止),线程总是重试获取锁定。 此外,频繁的线程上下文切换可能会导致切换开销,从而降低系统的整体性能。
3 .确保线程始终以严格的顺序请求锁定
说起来容易做起来难。 如果要编写将账户a的资金转移到b的函数,可以编写以下内容:
//at compile time,第一个角落的we take lock第一次锁定,第二次
公共语音传输器(帐户,帐户b,长期)。
已同步(a ) {
已同步(b ) {
添加(亚马逊;
b .辅助(amount;
}
}
}
//atruntimewecannottrackhowourmethodswillbecalled
公共语音运行()
new Thread ()-this .传输(x ) ) x,y,10000 ) ) ) .开始);
new Thread ()-this .传输(y ) y,x,10000 ) ) ) .开始);
}
//this run (微信地址锁定)
//x的第一预测锁定,y的等待
//第二个预测锁定在y,waits for X
现实中的解决方案
锁定序列与定时器锁定的方法相结合,可以得到真正现实的解决方案
1 .在业务中决定锁定的顺序
根据账户大小区分a和b,可以改进方法。
//at运行时间,wetakelockonaccountwithsmalleridfirst
公共语音传输器(帐户,帐户b,长期)。
最终账户第一个=a.id b.id? A : B;
最终账户第二个=第一个==a? B: A;
已同步(第一) {
已同步(第二) {
first.add (亚马逊;
subtract (亚马逊;
}
}
}
//atruntimewecannottrackhowourmethodswillbecalled
公共语音运行()
new Thread ()-this .传输(x ) ) x,y,10000 ) ) ) .开始);
new Thread ()-this .传输(y ) y,x,10000 ) ) ) .开始);
}
如果X.ID=1111和Y.id=2222,则第一个帐户是小帐户id,因此锁定顺序与传输(y,x,10000 ) x、y和10000相同如果x的帐户小于y,则两个线程将尝试在y之前锁定x,并且仅在x成功之后继续锁定y。
2 .确定业务为tryLock/async的等待时间的锁定请求
使用上述业务可靠锁定序列的解决方案只适用于一个位置的逻辑迁移() )的关联关系,如决定如何协调资源的方法。
最终有其他方法/逻辑,最终可能会使用与其不兼容的排序逻辑transfer(…)。 为了防止在这种情况下发生死锁,建议使用异步锁定。 尝试锁定了资源有限/实际时间(最大事务时间)的小随机等待时间。 这样,所有线程都不会单独快速获得锁定,从而避免了活动块。 无法获得锁定,多次尝试,结果导致饥饿。
//assume account # get lock (千兆计数’ slock (Java.util.concurrent.locks.lock ) ) ) ) ) ) ) ) ) )
//帐户代码加密锁定,提供锁定() /解锁) ) )。
公共长整型等待(
//returnsmovingaverageoftransfertimesforlastntransferssmall-random-saltinmillissoallthreadswaitingtolockdonotwakeupattttttto
//////因为返回最后n次传输的传输时间的移动平均值小的随机时间,所以等待锁定的所有线程不会同时唤醒。
}
公共语音传输器(锁定锁定、锁定、入站)。
最终账户第一个=a.id b.id? A : B;
最终账户第二个=第一个==a? B: A;
最终锁定锁定=first.get锁定(;
最终锁定=第二个锁定(;
布尔东=假;
DO {2}
特里
特里
if (lockf.trylock (获取等待(、毫米波) ) ) ) ) ) ) ) ) ) ) ) ) ) )。
特里
if (locks.trylock (获取等待(、毫米波) ) ) ) ) ) ) ) ) ) ) ) ) )。
完全=真;
}
} finally {
lockS.unlock (;
}
}
} catch (交替描述符) )
thrownewruntimeexception (已取消);
}
} finally {
lockF.unlock (;
}
} while (! 完全;
}
//atruntimewecannottrackhowourmethodswillbecalled
公共语音运行()
new Thread ()-this .传输(x ) ) x,y,10000 ) ) ) .开始);
new Thread ()-this .传输(y ) y,x,10000 ) ) ) .开始);
}