java多线程学习之死锁的模拟和避免(实例讲解)

  

  

死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。

  

  

1,互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用

  

2,不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。

  

3,请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。

  

4,循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

  

当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。

  

        包com.tl.skyLine.thread;      进口java.util.Date;/* *   *由tl>   星期五3月03 16:34:36中科2017陈顶天开始拿餐具吃饭   星期五3月03 16:34:37中科2017陈顶天抢到了筷子   星期五3月03 16:34:36中科2017邹保健开始拿餐具吃饭   星期五3月03 16:34:37中科2017邹保健抢到了碗      

结果陈顶天同学抢到了参筷子,拿着不放,邹保健同学抢到了碗,也死活不放的手,但是只有一双筷子和一双碗,结果就是双双饿死…

  

  

假如我们是陈顶天和邹保健同学的同事,肯定不忍心看到他们饿死,那么怎么办呢?

  

我们就要采取方法避免思索的发生,这边介绍两种方法,(线程按照一定的顺序加锁);(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁);

  

<强> 3.1加锁顺序

  

当多个线程需要相同的一些锁,但是按照不同的顺序加锁、死锁就很容易发生。如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。我们上面的代码为了模拟死锁,将线程LockA与LockB两位同事的抢夺资源顺序做了一个调整,LockA先抢碗,然后sleep3秒,LockB先抢筷子,我们现在把争夺资源顺序改一下,两个线程都是先抢碗,再抢筷子,严格按照这个顺序运行,那么一个抢到碗以后,B去争夺资源,必须从抢碗开始,不能在抢不到碗的情况下去抢筷子,这样就避免死锁的发生,这也是避免死锁最简单的方法。

  

<强>代码修改如下:

     /* *   *由tl>   2017年3月24日11:16:51 CST星期五邹保健开始拿餐具吃饭   2017年3月24日11:16:51 CST星期五陈顶天开始拿餐具吃饭   2017年3月24日11:16:51 CST星期五邹保健抢到了碗   2017年3月24日11:16:51 CST星期五邹保健抢到了筷子   2017年3月24日11:16:51 CST星期五陈顶天抢到了碗   2017年3月24日11:16:51 CST星期五陈顶天抢到了筷子   2017年3月24日11:16:56 CST星期五邹保健抢到了碗   2017年3月24日11:16:56 CST星期五邹保健抢到了筷子   2017年3月24日11:16:56 CST星期五陈顶天抢到了碗   2017年3月24日11:16:56 CST星期五陈顶天抢到了筷子   2017年3月24日11:17:01 CST星期五邹保健抢到了碗   2017年3月24日11:17:01 CST星期五邹保健抢到了筷子      

就不会再出现死锁的情况了。

  

<强> 3.2加锁时效

  

加锁时效的原理就是:给每一个访问线程增加访问时效,若一个线程没有在给定的时限内成功获得所有需要的锁,则会进行回退并释放所有已经获得的锁(此时就打破了造成死锁的四个原因中的第三个原因),然后等待一段随机的时间再重试。

  

为了实现这个目标,我们不使用显示的去锁,我而是用信号量信号去控制。信号量可以控制资源能被多少线程访问,这里我们指定只能被一个线程访问,就做到了类似锁住。而信号量可以指定去获取的超时时间,我们可以根据这个超时时间,去做一个额外处理。对于无法成功获取的情况,一般就是重复尝试,或指定尝试的次数,也可以马上退出。

        包com.tl.skyLine.thread;      进口java.util.Date;   进口java.util.concurrent.Semaphore;   进口java.util.concurrent.TimeUnit;/* *   *由tl>   星期五3月03 18:12:07中科2017邹保健开始拿餐具吃饭   星期五3月03 18:12:07中科2017陈顶天开始拿餐具吃饭   星期五3月03 18:12:07中科2017邹保健抢到了碗   星期五3月03 18:12:07中科2017陈顶天抢到了筷子   星期五3月03 18:12:08中科2017筷子已经被抢走了,邹保健抢筷子失败   星期五3月03 18:12:08中科2017邹保健把抢到的部分餐具又放回原处   星期五3月03 18:12:08中科2017陈顶天抢到了碗,凑齐了餐具,准备吃饭   星期五3月03 18:12:10中科2017碗已经被抢走了,邹保健抢碗失败   星期五3月03 18:12:10中科2017邹保健把抢到的部分餐具又放回原处   星期五3月03 18:12:11中科2017邹保健抢到了碗   星期五3月03 18:12:11中科2017邹保健抢到了筷子,凑齐了餐具,准备吃饭

java多线程学习之死锁的模拟和避免(实例讲解)