为了测试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、在生产者--消费者模型中,使用仓库的概念使得生产者与消费者脱离,即生产者不会需要去拿消费者的锁,消费者也不会去需要拿生产者的锁。他们只需要去拿仓库的锁。
得到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、在生产者--消费者模型中,使用仓库的概念使得生产者与消费者脱离,即生产者不会需要去拿消费者的锁,消费者也不会去需要拿生产者的锁。他们只需要去拿仓库的锁。