多线程基础总结一--synchronized
2010-01-22 00:00:00 来源:WEB开发网假设场景:线程A调用methodOne(),获得lock1的隐式锁后,在获得lock2的隐式锁之前线程B进入运行,调用 methodTwo(),抢先获得了lock2的隐式锁,此时线程A等着线程B交出lock2,线程B等着lock1进入方法块,死锁就这样被创造出来了。
以上的例子不直观的话,再看一个实例顺便看看wait()的缺陷:
Java代码
import java.util.LinkedList;
import java.util.List;
/**
* User: yanxuxin
* Date: Dec 9, 2009
* Time: 5:58:39 PM
*/
public class DeadLockSample {
public static void main(String[] args) {
final WaitAndNotify wan = new WaitAndNotify();
Thread t1 = new Thread(new Runnable(){
public void run() {
wan.pop();
}
});
Thread t2 = new Thread(new Runnable(){
public void run() {
wan.push("a");
}
});
t1.start();
t2.start();
}
}
class WaitAndNotify {
final List<String> list = new LinkedList<String>();
public synchronized void push(String x) {
synchronized(list) {
list.add(x);
notify();
}
}
public synchronized Object pop() {
synchronized(list) {
if(list.size() <= 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return list.size();
}
}
}
上面的这个例子也会出现死锁,为什么呢?首先看WaitAndNotify这个类,在push和pop方法上有synchronized关键字,方法内部也有synchronized,那么当WaitAndNotify实例化时会有两个对象的隐式锁,一个是WaitAndNotify对象自身的,作用在方法上;另一个就是方法内部同步用到的list的。主线程开启两个线程t1和t2,t1进入pop方法此时list为空,它先后获得了wan和 list的隐式锁,接着就被wait扔进wait set等待去了。注意这个wait()方法是谁的?答案是wan的,所以它释放了wan的隐式锁,但是把list的死死的抓着不放。此时t2终于得到了 wan的隐式锁进入push方法,但是不幸的是list的隐式锁它这辈子也得不到了。。。
就是由于wait的设计是针对对象管理线程的,而又没有其他的可以类似栈的方式层层释放锁,导致死锁的杯具了。关于synchronized和 wait(),notify(),notifyAll()的故事,我想我能瞎编的暂时这么多了,不然滔滔江水就又杯具了,哈哈。下面简单的讲讲 java.lang.Thread的特色小故事。(待续...)
PS:"多线程基础总结六"算是本文的补遗了,呵呵。
更多精彩
赞助商链接