同步会导致另一个可能的问题就是死锁(deadlock)。如果两个线程需要独占访问统一的一个资源集,而每个线程分别有这些资源的不同子集锁,就会发生死锁。如果两个线程都不愿意放弃已经拥有的资源,就会进入无限停止状态。
下面是一个简单的死锁例子
public classDeadLock {
public static final Stringres1="res1";
public static final Stringres2="res2";
public static void main(String[] args) {
Thread lock1 = new Thread(new Lock1());
lock1.start();
Thread lock2 = new Thread(new Lock2());
lock2.start();
}
static class Lock1 implements Runnable {
@Override
public void run() {
synchronized(DeadLock.res1) {
System.out.println("thread-1 locked res1");
try{
Thread.sleep(300);
synchronized(DeadLock.res2) {
System.out.println("thread-1 locked res2");
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Lock2 implements Runnable {
@Override
public void run() {
synchronized(DeadLock.res2) {
System.out.println("thread-2 locked res2");
try{
Thread.sleep(300);
synchronized(DeadLock.res1) {
System.out.println("thread-2 locked res1");
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
要防止死锁,最重要的技术是避免不必要的同步。如果有其它方法可以确保线程安全,比如让对象不可变或保存对象的一个局部副本。如果确实要使用同步,要保持同步块尽可能小,而且尽量不要一次同步多个对象。
网友评论