黑马程序员:Java基础——多线程的死锁问题,黑马java
黑马程序员:Java基础——多线程的死锁问题,黑马java
------- Java EE培训、java培训、期待与您交流! ----------
1.概念
说到锁,我们日常生活中有过锁无法打开的情况,在Java中也有这种情况,那么这种情况被称为死锁。
死锁:所谓死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁.
产生死锁的原因主要有:
1.两个以上的进程
2.争夺共享的资源
3.它们各自不释放手中资源,除非有外力协助
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件
1.互斥条件:一个资源每次只能被一个进程使用。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
2.举例
我们来举个形象的例子:
三个人(A,B,C)玩三个球(1,2,3),规则很简单:每个人都必须先拿到自己左手边的球,才能拿自己右手边的求,两手都有球后,才能把球都放下。如图:
这个游戏看起来似乎可以永远进行下去,但是若干局后,如果三个人刚好都只拿到自己左手边的球,都等着拿右手边的球,但是因为谁都不放手,那么这三个人都将陷入无尽的等待中了。
接下来我们来用Java代码体现:
class Test implements Runnable{
private boolean flag;
Test(boolean flag){
this.flag=flag;
}
public void run(){
if(flag){
while(true){ //线程t1进入
synchronized (MyLock.lockA) {
System.out.println("if LockA");
synchronized (MyLock.lockB) {
System.out.println("if LockB");
}
}
}
}else{
while(true){ //线程t2进入
synchronized (MyLock.lockB) {
System.out.println("else LockB");
synchronized (MyLock.lockA) {
System.out.println("else LockA");
}
}
}
}
}
}
class MyLock{
static Object lockA = new Object(); //新建对象lockA
static Object lockB = new Object(); //新建对象lockB
}
public class ThreadSyncDeadLock {
public static void main(String[] args) {
Thread t1 = new Thread(new Test(true)); //给线程一传入true值
Thread t2 = new Thread(new Test(false)); //给线程二传入false值
t1.start();
t2.start();
}
}
我们来运行一下,看看结果:
我们多运行几次:
发现只出现了这两种情况,也就是说,我们看到的运行结果应该是:
if LockA
else LockB
if LockB
else LockA
...
这是因为程序在运行状态中由于一个资源每次只能被一个进程使用且一个进程因请求资源而阻塞时,对已获得的资源保持不放,并且进程已获得的资源,在末使用完之前,无法被强行剥夺。导致了两个进程循环等待。
我们可以这样理解,如下图:
2.死锁解决
那么我们该如何解决呢?
1、让所有的线程按照同样的顺序获得一组锁。这种方法消除了线程的拥有者分别等待对方的资源的问题。
2、将多个锁组成一组并放到同一个锁下。前面Java线程死锁的例子中,可以创建一个对象的锁。于是在获得数据之前都必须获得同一组锁。
3、将那些不会阻塞的可获得资源用变量标志出来。当某个线程获得一个对象的锁时,就可以通过检查变量来判断是否整个对象集合中的对象锁都可获得。如果是,它就可以获得相关的锁,否则,就要释放掉此对象这个锁并稍后再尝试。
相关文章
- 暂无相关文章
用户点评