在多线程编程中,要避免死锁的出现。
在Java中,同步的锁被必须是同一个对象才能保证同步。
死锁:同步代码中嵌套同步代码,两个线程的锁对象相同。
下面是会造成死锁的代码:
class Test implements Runnable{
private boolean flag;
Test(boolean flag){
this.flag=flag;
}
public void run(){
if(flag){
synchronized(MyLock.locka){
System.out.println("if laocka");
synchronized(MyLock.lockb){
System.out.println("if laockb");
}
}
}else{
synchronized(MyLock.lockb){
System.out.println("else laockb");
synchronized(MyLock.locka){
System.out.println("else laocka");
}
}
}
}
}
class MyLock{
/**
*创建两个不同的对象作为锁。
*/
public static MyLock locka=new MyLock();
public static MyLock lockb=new MyLock();
}
class MainClass{
public static void main(String[] args){
Thread t1=new Thread(new Test(true));
Thread t2=new Thread(new Test(false));
t1.start();
t2.start();
}
}
执行结果类似于(有的时候代码会全部执行完):
else lockb
if locka
因为t2线程打印else lockb时,继续往下执行需要MyLock.locka对象的锁,而该对象已经被t1线程上锁,t2无法进入,只能等待t1释放该对象的锁。
与此同时,t1线程打印了if locka,继续往下执行需要MyLock.lockb对象的锁,而该对象已经被t2线程上锁(因为t2没有执行结束,在等待,该锁不能释放),无法进入代码块,等待t2释放MyLock.lockb对象的锁。
两个线程都在等待对方释放锁,所以造成了死锁。
防止死锁的方式:
避免不同的同步代码块使用同样的对象作为锁。