并发编程是指多个线程同时进行,对同一资源进行操作,那么就会产生并发问题。如何解决?可以用锁。synchronized是最常用的,但是有时难免会出现死锁的现象。
下面就以一个实例讲解死锁的过程:
假定有一个分布式微博工具,下面是其后台代码。在她的propagateUPdate()方法被调用时,ExampleTimingNode类会收到更新,也可以查询看它是否收到了特定更新。
package com.Test.Tread;
public class MicroBlogNode implements SimpleMicroBlogNode{
private final String ident;
public MicroBlogNode(String ident_){
ident = ident_;
}
public String getIdent(){
return ident;
}
public synchronized void propagateUpdate(Update upd_,MicroBlogNode backup_) {
System.out.println(ident +": recvd: "+upd_.getUpdateText()+" ; banckup: "backup_.getIdent());
backup.confirmUpdate(this,upd_);
}
public synchronized void confirmUpdate(MicroBlogNode other_,Update update_) {
System.out.println(ident +": recvd confirm: "+update_.getUpdateText() +" from "+other_.getIdent());
}
}
final MicroBlogNode local = new MicroBlogNode("localhost:8888");
final MicroBlogNode other = new MicroBlogNode("localhost:8988");
final Update first = getUpdate("1");
final Update second = getUPdate("2");
new Thread(new Runnable(){
public void run(){
local.propagateUpdate(first,other);
}
}).start();
new Thread(new Runnable(){
public void run(){
other.propagateUpdate(second,local);
}
}).start();
上述中有两个更新分别发送给不同的线程,每一个都必须由后备线程进行确认,如此看来似乎没什么问题,但是实际执行起来就会发生死锁问题,,每个线程都说自己收到了更新,因为每个线程在确认方法能够得到确认之前都要求另一个线程释放线程锁。
本例中第一个线程以A(propagateUpdate),B(confirmUpdate)的顺序获得锁,而第二个线程以B,A的方式获得线程锁,有一个处理死锁的技巧:两个线程都已A,B的顺序获得线程锁即可。
两个线程两把锁,若是以不同的顺序获得锁就很有可能发生死锁现象。