死锁:两个线程都在等待彼此先完成,造成了程序的停滞,一般程序的死锁都是在程序运行时出现的。
一般造成死锁必须同时满足如下4个条件:
1,互斥条件:线程使用的资源必须至少有一个是不能共享的;
2,请求与保持条件:至少有一个线程必须持有一个资源并且正在等待获取一个当前被其它线程持有的资源;
3,非剥夺条件:分配资源不能从相应的线程中被强制剥夺;
4,循环等待条件:第一个线程等待其它线程,后者又在等待第一个线程。
因为要产生死锁,这4个条件必须同时满足,所以要防止死锁的话,只需要破坏其中一个条件即可。
死锁代码示例:
class Conductor{
public void sellTicket(){
System.out.println("Conductor say to passenger 给我钱,就给你票");
}
public void get(){
System.out.println("Conductor 拿到了钱");
}
}
class Passenger{
public void buyTicket(){
System.out.println("Passenger say to Conductor 给我票,就才给你钱");
}
public void get(){
System.out.println("Passenger 拿到了票");
}
}
class Test implements Runnable{
private boolean flag;
Test(boolean flag){
this.flag = flag;
}
private static Conductor c = new Conductor();
private static Passenger p = new Passenger();
public void run(){
if(flag){
while(true){
synchronized(c){
c.sellTicket();
synchronized(p){
c.get();
}
}
}
}else{
while(true){
synchronized(p){
p.buyTicket();
synchronized(c){
p.get();
}
}
}
}
}
}
class DeadLocakDemo{
public static void main(String[] args){
Test t1 = new Test(true);
Test t2 = new Test(false);
new Thread(t1).start();
new Thread(t2).start();
}
}
运行结果:
从程序的运行结果中可以发现,两个线程都在彼此等待着对方的执行完成,这样,程序就无法向下继续执行,从而造成了死锁的现象。
大部分代码并不容易产生死锁,死锁可能在代码中隐藏相当长的时间,等待不常见的条件地发生,但即使是很小的概率,一旦发生,便可能造成毁灭性的破坏。避免死锁是一件困难的事,遵循以下原则有助于规避死锁:
1、只在必要的最短时间内持有锁,考虑使用同步语句块代替整个同步方法;
2、尽量编写不在同一时刻需要持有多个锁的代码,如果不可避免,则确保线程持有第二个锁的时间尽量短暂;
3、创建和使用一个大锁来代替若干小锁,并把这个锁用于互斥,而不是用作单个对象的对象级别锁;
摘自:http://blog.csdn.net/ns_code/article/details/17200937