同步过程中,如果一个对象占有了一个资源,等待着另一个被其它对象占有的资源,如果这个“其它对象”也正在等待这个对象已经拥有的资源,那么会引起死锁。但也不需要矫枉过正,下边示例并不是一个有潜在引起死锁的例子:
import java.util.ArrayList;
import java.util.List;
public class NameList {
private List names = new ArrayList();
public synchronized void add(String name){
names.add(name);
}
public synchronized void printAll(){
for(int i=0;i<names.size();i++){
System.out.println(names.get(i) + " ");
}
}
public static void main(String[] args) {
final NameList s1 = new NameList();
for(int i=0;i<2;i++){
new Thread(){
public void run(){
s1.add("A");
s1.add("B");
s1.add("C");
s1.printAll();
System.out.println();
}
}.start();
}
}
}
add(String name)和printAll()都是共享资源s1上的同步方法,绝对不会死锁!java的锁可以认为是可重入的,synchronized 保证一个方法在同一时刻只被一个方法占有,而且必须执行完毕其它线程进入。
导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问。synchronized 关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,因此,被允许执行的线程首先必须拥有对变量或对象的排他性访问权。当线程访问对象时,线程会给对象加锁,而这个锁导致其它也想访问同一对象的线程被阻塞,直至第一个线程释放它加在对象上的锁。 上述程序,始终锁定了一个对象,那么限制了另外一个线程锁定它,继而执行run的代码体 |