您的位置:首页 > 其它

死锁的产生以及如何防止死锁的产生

2016-06-03 21:17 274 查看
不多说,先来看一个例子:

class Car{
Exception c;
private boolean waxOn=false;//waxOn表示的是正在打蜡。
public  synchronized void waxed(){//当打蜡完成的时候,就将抛光的线程唤醒
waxOn=true;
notifyAll();
}

public synchronized  void buffed(){//表示抛光的动作已经完成了,又将打蜡的线程唤醒
waxOn=false;
notifyAll();
}

public synchronized  void waitForWaxing() {//这个表示的是线程在灯光打蜡的动作完成
while (waxOn = false) {
try {
wait();//这里的话,表示的是一直等待,知道别人把这个给唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public synchronized  void waitForBuffing() {//这里表示的是等待抛光的动作完成
while (waxOn = true) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//这个表示的是抛光的过程
class WaxOn implements  Runnable{
private Car car;

public WaxOn(Car car) {
this.car=car;
}

@Override
public void run() {
try {
while (!Thread.interrupted()) {
System.out.println("Wax on");
TimeUnit.MILLISECONDS.sleep(200);
car.waxed();
car.waitForBuffing();
}
} catch (InterruptedException e) {
System.out.println("Exiting via interrupt");
}
System.out.println("Ending Wax  Off task");
}
}

//这个表示的是打蜡完成,抛光的过程
class WaxOff implements  Runnable{
private Car car;

public WaxOff(Car car) {
this.car=car;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
car.waitForWaxing();//这个表示的是在抛光之前必须等待打蜡过程的完成。
System.out.println("Wax off");//表示的是打蜡过程完成了
TimeUnit.MILLISECONDS.sleep(200);//这个表示的是抛光所需要的时间
car.buffed();//这个表示的是正在抛光
}
} catch (InterruptedException e) {
System.out.println("Exiting via interrupt");
}
System.out.println("Ending Wax off task");

}
}

public class WaxOMatic {
}
public static void main(String[] args){
Car car=new Car();
ExecutorService exec= Executors.newCachedThreadPool();
exec.execute(new WaxOff(car));
exec.execute(new WaxOn(car));
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
exec.shutdownNow();
}

}
以下的这个例子也是一样的,只是使用了不同的方法而已:
class WaxOn implements  Runnable{//这是涂蜡任务
WaxOMatic waxOMatic;
public WaxOn(WaxOMatic waxOMatic) {
this.waxOMatic=waxOMatic;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
while (!waxOMatic.flag) {//flag为false的时候,表示的是正在等待。
wait();
}
}
System.out.println("这俩车正在打蜡");
waxOMatic.flag=false;
synchronized (waxOMatic.waxOff) {
waxOMatic.waxOff.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}

class WaxOff implements  Runnable{//这是抛光任务
private WaxOMatic waxOMatic;
public WaxOff(WaxOMatic waxOMatic) {
this.waxOMatic=waxOMatic;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
while (waxOMatic.flag) {
wait();
}
}
System.out.println("这俩车正在抛光");
waxOMatic.flag=true;
synchronized (waxOMatic.waxOn) {
waxOMatic.waxOn.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}
public class WaxOMatic {
    WaxOn waxOn = new WaxOn(this);
    WaxOff waxOff = new WaxOff(this);
    boolean flag=true;
    ExecutorService exec= Executors.newCachedThreadPool();
    public WaxOMatic() {
        exec.execute(waxOn);
        exec.execute(waxOff);
    }
    public static void main(String[] args){
        new WaxOMatic();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.exit(0);
    }
}

程序的输出的结果为:

这俩车正在打蜡
这俩车正在抛光
这俩车正在打蜡
这俩车正在抛光

我们再来看一下另外一种形式的代码:

/*这个程序主要处理的是汽车的打蜡和抛光的任务*/
class Car{
    //只是一个标志
    boolean flag=true;

    //表示的是正在涂蜡
    public synchronized  void WaxOn() {
        try {
            while (!Thread.interrupted()) {
                synchronized (this) {
                    while (!flag) {
                        wait();
                    }
                }
                System.out.println(Thread.currentThread().getName()+"正在打蜡");
                TimeUnit.MILLISECONDS.sleep(500);//表示的是打蜡需要的时间
                notifyAll();
                flag=false;//打蜡完成以后,需要等待抛光完成了以后,才能继续完成下一次的打蜡。因此需要等待
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    //表示的是正在抛光
    public synchronized  void buff() {
        try {
            while (!Thread.interrupted()) {
                synchronized (this) {
                    while (flag) {
                        wait();
                    }
                }
                System.out.println(Thread.currentThread().getName()+"正在抛光");
                TimeUnit.MILLISECONDS.sleep(500);//表示的是抛光需要的时间
                notifyAll();
                flag=true;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}
class WaxOn implements  Runnable{
    private Car car;//关联上的是同一份的资源

    public WaxOn(Car car) {
        this.car=car;
    }

    @Override
    public void run() {
        car.WaxOn();
    }
}

class Buff implements  Runnable{
    private Car car;

    public Buff(Car car) {
        this.car=car;
    }
    @Override
    public void run() {
        car.buff();
    }
}

public class WaxOMatic{
    public static void main(String[] args){
       Car car=new Car();
        ExecutorService exec= Executors.newCachedThreadPool();
        WaxOn waxOn = new WaxOn(car);
        Buff buff = new Buff(car);
        for(int i=0;i<5;i++){
        exec.execute(waxOn);
        exec.execute(buff);
        }
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        
       System.exit(0);
    }

}

最后的输出的结果为:

pool-1-thread-1正在打蜡
pool-1-thread-10正在抛光
pool-1-thread-9正在打蜡
pool-1-thread-6正在抛光
pool-1-thread-7正在打蜡
pool-1-thread-4正在抛光
pool-1-thread-3正在打蜡
pool-1-thread-2正在抛光
pool-1-thread-3正在打蜡
pool-1-thread-4正在抛光
pool-1-thread-5正在打蜡
pool-1-thread-6正在抛光
pool-1-thread-9正在打蜡
pool-1-thread-8正在抛光
pool-1-thread-1正在打蜡
pool-1-thread-10正在抛光
pool-1-thread-9正在打蜡
pool-1-thread-6正在抛光
pool-1-thread-7正在打蜡
pool-1-thread-4正在抛光

现在我们再来看一看使用显式的lock和condition是如何实现防止死锁的产生的。

class Car {
//只是一个标志
boolean flag = true;
private Lock lock = new ReentrantLock();
private Condition condition=lock.newCondition();

//表示的是正在涂蜡
/*注意在这个方法中,由于是使用了显式的Lock和condition,那么就不能使用synchronized了,这是要注意的
* 也就是不能这样写:public void waxOn,否则是打不开的*/
public  void WaxOn() {
try {
while (!Thread.interrupted()) {
lock.lock();

try {
while (!flag) {
condition.await();
}
} finally {
lock.unlock();
}

System.out.println("正在打蜡");
TimeUnit.MILLISECONDS.sleep(500);
// notifyAll();
condition.signalAll();
flag = false;//打蜡完成以后,需要等待抛光完成了以后,才能继续完成下一次的打蜡。因此需要等待

}
} catch (InterruptedException e) {
e.printStackTrace();
}

}

//表示的是正在抛光
public  void buff() {
try {
while (!Thread.interrupted()) {
//使用显式的Lock
lock.lock();
try {
while (flag) {
condition.await();
}
} finally {
lock.unlock();
}

System.out.println("正在抛光");
TimeUnit.MILLISECONDS.sleep(500);
// notifyAll();
//一般来说,使用这个condition.signalAll()的话,比使用notifyAll()更好,效率更高
condition.signalAll();
flag = true;

}
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}
class WaxOn implements  Runnable{
private Car car;//关联上的是同一份的资源

public WaxOn(Car car) {
this.car=car;
}

@Override
public void run() {
car.WaxOn();
}
}

class Buff implements  Runnable{
private Car car;

public Buff(Car car) {
this.car=car;
}
@Override
public void run() {
car.buff();
}
}

public class WaxOMatic{
public static void main(String[] args){
Car car=new Car();
ExecutorService exec= Executors.newCachedThreadPool();
WaxOn waxOn = new WaxOn(car);
Buff buff = new Buff(car);
exec.execute(waxOn);
exec.execute(buff);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.exit(0);
}

}
最后的输出的结果为:
正在打蜡
正在抛光
正在打蜡
正在抛光
正在打蜡
正在抛光

其实为了防止唤醒自己的同类,那么我们可以使用不同的condition来进行处理:

/*我们来看看如何利用显示的Lock和Condition来防止这种情况的发生*/

class Car {
    //只是一个标志
    boolean flag = true;
    private Lock lock = new ReentrantLock();
    //可以使用不同的condition来处理,这样的话,可以避免唤醒自己的同类。其实,在线程中,队列也是这样实现的。
    private Condition condition=lock.newCondition();
    private Condition condition2=lock.newCondition();
    //表示的是正在涂蜡
    //注意在这个方法中,不能再使用synchronized,否则是不正确的
    //也就是不能写为public synchronized void waxOn
    public   void  WaxOn() {
        try {
            while (!Thread.interrupted()) {
                   lock.lock();

                try {
                    while (!flag) {
                        condition.await();
                    }
                    System.out.println("正在打蜡");
                   
                    condition2.signal();
                    flag = false;
                    // notifyAll();
                   
                   
                  
                  
       
                    
                    
                    TimeUnit.MILLISECONDS.sleep(500);
                   //打蜡完成以后,需要等待抛光完成了以后,才能继续完成下一次的打蜡。因此需要等待
                } finally {
                    lock.unlock();
                }
             
                
                  
             
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    //表示的是正在抛光
    public   void  buff() {
        try {
            while (!Thread.interrupted()) {
                //使用显式的Lock
                  lock.lock();
                try {
                    while (flag) {
                        condition2.await();
                     }
                    System.out.println("正在抛光");
                    
                    // notifyAll();
                    //一般来说,使用这个condition.signalAll()的话,比使用notifyAll()更好,效率更高
                  
                   condition.signal();
                   flag = true;
                   
                  
                  TimeUnit.MILLISECONDS.sleep(500);
                } finally {
                    lock.unlock();
                }
                
                   
          
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}
class WaxOn implements  Runnable{
    private Car car;//关联上的是同一份的资源

    public WaxOn(Car car) {
        this.car=car;
    }

    @Override
    public void run() {
        car.WaxOn();
    }
}

class Buff implements  Runnable{
    private Car car;

    public Buff(Car car) {
        this.car=car;
    }
    @Override
    public void run() {
        car.buff();
    }
}

public class WaxOMatic{
    public static void main(String[] args){
        Car car=new Car();
        ExecutorService exec= Executors.newCachedThreadPool();
        WaxOn waxOn = new WaxOn(car);
        Buff buff = new Buff(car);
        exec.execute(waxOn);
        exec.execute(buff);
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.exit(0);
    }

其实,代码都是差不多的,只是改了其中的一点点。最后输出的结果也是一样的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: