一、死锁
所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。百科百科
当两个以上的运算单元,双方都在等待对方停止运行,以取得系统资源,但是没有一方提前退出时,这种状况,就称为死锁。维基百科
1. 顺序死锁
最少有两个锁,一个线程获取到A锁需要获取B锁才能进行操作,而另外一个线程获取到了B锁,需要获取A锁才能执行操作,这种情况下容易出现顺序死锁。
[java]view plaincopy
publicclassLeftRightDeadlock {
privatefinalObject left =newObject();
privatefinalObject right =newObject();
publicvoidleftRight() {
synchronized(left) {
synchronized(right) {
// doSomething();
}
}
}
publicvoidrightLeft() {
synchronized(right) {
synchronized(left) {
// doSomething();
}
}
}
}
2. 动态的锁顺序死锁
[java]view plaincopy
publicvoidtransferMoney(Account fromAccount, Account toAccount, DollarAmount anount)
throwsInsufficientResourcesException {
synchronized(fromAccount) {
synchronized(toAccount) {
if(fromAccount.getBalance().compareTo(amount) <0) {
thrownewInsufficientResourcesException();
}else{
fromAccount.debit(anount);
toAccount.credit(anount);
}
}
}
}
A: transferMoney(myAccount, yourAccount, 10);
B: transferMoney(yourAccount, myAccount, 20);
由外部传入的变量所有锁的条件,但是由以上传入的变量可以看到,这种情况下会出现一个线程先获取myAccount锁在申请yourAccount锁,而另外一个线程相反先获取yourAccount锁在申请myAccount锁。
[java]view plaincopy
privatestaticfinalObject tieLock =newObject();
publicvoidtransferMoney(finalAccount fromAccount,finalAccount toAccount,finalDollarAmount anount)
throwsInsufficientResourcesException {
classHelper{
publicvoidtransfer()throwsInsufficientResourcesException {
if(fromAccount.getBalance().compareTo(amount) <0){
thrownewInsufficientResourcesException();
}else{
fromAccount.debit(anount);
toAccount.credit(anount);
}
}
}
intfromHash = System.identityHashCode(fromAccount);
inttoHash = System.identityHashCode(toAccount);
if(fromHash < toHash){
synchronized(fromAccount){
synchronized(toAccount) {
newHelper().transfer();
}
}
}elseif(fromHash > toHash){
synchronized(toAccount){
synchronized(fromAccount) {
newHelper().transfer();
}
}
}else{
synchronized(tieLock) {
synchronized(fromAccount) {
synchronized(toAccount) {
newHelper().transfer();
}
}
}
}
}
3. 在协作对象之间发生的死锁
[java]view plaincopy
classTaxi {
privatePoint location, destination;
privatefinalDispatcher dispatcher;
publicTaxi(Dispatcher dispatcher) {
this.dispatcher = dispatcher;
}
publicsynchronizedPoint getLocation(){
returnlocation;
}
publicsynchronizedvoidsetLocation(Point location){
this.location = location;
if(location.equals(destination)){
dispatcher.notifyAvaliable(this);
}
}
}
classDispatcher {
privatefinalSet taxis;
privatefinalSet avaliableTaxis;
publicDispatcher(){
taxis =newHashSet();
avaliableTaxis =newHashSet();
}
publicsynchronizedvoidnotifyAvaliable(Taxi taxi) {
avaliableTaxis.add(taxi);
}
publicsynchronizedImage getImage(){
Image image =newImage();
for(Taxi t :taxis){
image.drawMarker(t.getLocation());
}
returnimage;
}
}
4. 开放调用
-- 待填充
5. 资源死锁
外部锁常被忽视而导致死锁,例如数据库的锁
1. 支持定时的死锁
存在一些预防死锁的手段,比如Lock的tryLock,JDK 7中引入的Phaser等。
2. 通过线程转储信息来分析死锁
通过Dump线程的StackTrace,例如linux下执行命令 kill -3 ,或者jstack –l ,或者使用Jconsole连接上去查看线程的StackTrace,由此来诊断死锁问题。
1. 饥饿
2. 糟糕的响应性
3. 活锁
使用支持CAS的数据结构,避免使用锁,如:AtomicXXX、ConcurrentMap、CopyOnWriteList、ConcurrentLinkedQueue
死锁经常是无法完全避免的,鸵鸟策略被很多基础框架所采用。
存在检测死锁的办法
以上就是我推荐给Java开发者们的一面试经典知识。但是这些知识里面并没有太多Java全栈、Java晋阶、JAVA架构之类的题,不是我不推荐,而是希望大家更多的从基本功做起,打好基础,太多复杂的内容一会儿也说不明白。
好了同学们,我能介绍的也都全部介绍完给你们了,如果下获得更多JAVA教学资源,可以选择来我们这里共同交流,群:240448376,很多大神在这里切磋学习,不懂可以直接问,晚上还有大牛免费直播教学。
注:加群要求
1、具有一定工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加,有些应届生和实习生也可以加。
2、在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加。
3、如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的,可以加。
4、觉得自己很牛B,一般需求都能搞定。但是所学的知识点没有系统化,很难在技术领域继续突破的可以加。
5.阿里Java高级大牛直播讲解知识点,分享知识,多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!
PS:现在主要讲解的内容是(反射原理、枚举原理与应用、注解原理、常用设计模式、正规表达式高级应用、JAVA操作Office原理详解、JAVA图像处理技术,等多个知识点的详解和实战)
6.小号或者小白之类加群一律不给过,谢谢。
最后,每一位读到这里的网友,感谢你们能耐心地看完。觉得对你有帮助可以给个喜欢!希望在成为一名更优秀的Java程序员的道路上,我们可以一起学习、一起进步