java多线程死锁实例,线程锁并不可怕

为了测试java多线程死锁

得到java多线程死锁的直观感觉,写出以下测试代码。

public class TestDeadLock
{
public static void main(String[] args)
{
   A a=new A();
   B b=new B(a);
   a.set(b);
   Thread t1=new Thread(a);
   Thread t2=new Thread(b);
   t1.start();
   t2.start();
}
}

class A implements Runnable
{
public B b;
public void run()
    {
   while (true)
   {
      synchronized(this)
      {
      b.write();
      }
   }
    }
public void write()
{
    synchronized (this)
    {
       System.out.println("a write");
    }
}
public void set(B b)
    {
   this.b=b;
    }
}
class B implements Runnable
{
public A a;
public B(A a)
    {
     this.a=a;
    }
public void write()
{
    synchronized (this)
    {
       System.out.println("b write");
    }
}
public void run()
    {
   while (true)
   {
      synchronized(this)
      {

      a.write();
      }
   }
    }
}

1、代码导读

对象a使用独立线程去调用对象b的方法。

对象b使用独立线程去调用对象a的方法。

对象a在调用b的方法之前对自己加锁,调用对象b后对对象b加锁。

对象b在调用a的方法之前对自己加锁,调用对象a后对对象a加锁。

2、死锁形成原因解读

a首先锁了自己,b锁了自己,

a去拿b的锁,发现b已经锁定了,则等待b的锁释放

b去拿a的锁,发现a已经锁定,则等待a释放。

就这样a等b,b也等a,造成了死锁的问题。

3、死锁的必要条件

两个或两个以上的线程在活动

某个线程拿到了一个锁以后,还想去拿第二个锁,即锁的嵌套

4、预防死锁的编程规范和方法。

@1、如果某个对象拿到了自己的锁,如果想要去拿另外对象的锁,一定要先释放自己的锁。任何锁嵌套都是不安全的

@2、加锁的代码块,其中尽量不要去调用另外的方法。因为很难在子方法中施放锁。如果需要调用到其他的方法,需确定该方法以及其子分支肯定不会申请本锁以外的锁。

@3、遇到锁中必须调用其他锁的情况,必须确定下个锁对象中不会再回调。所有锁调用都是拓扑序的。

@4、在生产者--消费者模型中,使用仓库的概念使得生产者与消费者脱离,即生产者不会需要去拿消费者的锁,消费者也不会去需要拿生产者的锁。他们只需要去拿仓库的锁。

posted @ 2015-10-24 23:46  果维  阅读(3440)  评论(0编辑  收藏  举报