天天看点

死锁的例子和 synchronized 嵌套使用

当synchronized使用过多时,可能会造成死锁,那么死锁到底是怎么一回事呢。先看下面的代码,实现死锁: 

java代码  

死锁的例子和 synchronized 嵌套使用

//死锁的实现  

class a  

{  

    public void get(){  

        system.out.println("a说:我开始启动了,b,给我你的资源");  

    }  

    public void say(){  

        system.out.println("a获得资源");  

}  

class b  

        system.out.println("b说:我开始启动了,a,给我你的资源");  

        system.out.println("b获得资源");  

class mythread implements runnable  

    public static a a = new a();  

    public static b b = new b();  

    public boolean flag = false;  

    public void run(){  

        if(flag){  

            synchronized(a){  

                a.get();  

                try{  

                    thread.sleep(500);  

                }catch(interruptedexception e){}  

                synchronized(b){     //此同步代码块在另一同步代码块里  

                a.say();  

                }  

            }  

        }else{  

            synchronized(b){  

                b.get();  

            synchronized(a){     //此同步代码块在另一同步代码块里  

                b.say();  

        }     

public class demo24  

    public static void main(string args[]){  

        mythread mt1 = new mythread();  

        mythread mt2 = new mythread();  

        mt1.flag=true;  

        mt2.flag=false;  

        thread th1 = new thread(mt1);  

        thread th2 = new thread(mt2);  

        th1.start();  

        th2.start();  

以上代码由于 synchronized 的同步造成了死锁,死锁是两个或多个线程同时等待对方的完成,而程序无法继续执行。在解释代码前,首先要明白synchronized到底是怎么一回事。synchronized 定义同步,那么同步的什么,什么和什么同步了? 

首先,我们得知道,什么是锁。在java中,每一个对象都有一个内部锁,如果以方法或代码块用 synchronized 进行声明,那么对象的锁将保护整个方法或代码块,要调用这个方法或者执行这个代码块,必须获得这个对象的锁。而且,任何时候都只能有一个线程对象执行被保护的代码 

在以上代码中,在线程th1启动后,他就获得了a的锁,同时当其休眠完毕,求会申请获得b的锁,而此时,他的a锁没有放弃。在线程th2启动后,他就获得了b的锁,同时当其休眠完毕,求会申请获得a的锁,而此时,他的b锁没有放弃。 

两方都握有自己的锁不放弃,而同时申请另一方的锁,所以,此时就造成了死锁。 

同步,同步的就是线程和对象,将线程和对象进行绑定,获取对象的锁。 

注意:通过以上代码可以发现,死锁的必要条件是不放弃已有的锁,而同时申请新锁。所以,要想实现死锁,就会有synchronized的嵌套。 

这样才能同时操作两个以上的锁,从而造成死锁。