下面的代码在绝大部分时间内都运行得很正常,请问在什么情况下会出现问题?问题的根源在哪里?
import java.util.LinkedList; public class Stack {
LinkedList list = new LinkedList(); public synchronized void push(Object x) {
synchronized(list) {
list.addLast( x );
notify();
}
} public synchronized Object pop()
throws Exception {
synchronized(list) {
if( list.size() <= 0 ) {
wait();
}
return list.removeLast();
}
}
}
import java.util.LinkedList; public class Stack {
LinkedList list = new LinkedList(); public synchronized void push(Object x) {
synchronized(list) {
list.addLast( x );
notify();
}
} public synchronized Object pop()
throws Exception {
synchronized(list) {
if( list.size() <= 0 ) {
wait();
}
return list.removeLast();
}
}
}
假设thread1 获取了对象锁,但是list.size() <= 0,所以该线程释放对象锁,并且等待。
有一个线程(thread3)获取对象锁,然后执行了 push,并且notify这时,thread1,和thread2都在争抢对象锁, 假设thread2抢到,那么list.size() ==1
thread2 pop了,然后释放对象锁,这时,list.size() ==0,
然后thread1获得对象锁, 可是它认为现在list.size() 〉0 ,结果可想而知
-----------
public synchronized void push(Object x) {
synchronized(list) {
list.addLast( x );
notify();
}
}
这个时候他获得2个锁,一个是Stack对象的锁,还有list对象的锁,而notify,释放的是stack对象的锁,没有释放list对象的锁
之所以大部分时间程序运行成功,是因为push总比pop快,list没有为0.
/**
* 模拟栈
* @author ybygjy
* @date 2009-3-18
*/
public class LinkListStack {
/**singlon模式*/
private static LinkListStack linkListStackObj = null;
/**内置创建线程安全的List*/
private LinkedList<Object> linkedList = (LinkedList<Object>) Collections.synchronizedList(new LinkedList<Object>());
/**
* Constructor 私有方法
*/
private LinkListStack() {
}
/**
* 得到栈实例
* @return linkListStackObj 栈实例
*/
public static final LinkListStack getLinkListStackInstance() {
if (linkListStackObj == null) {
linkListStackObj = new LinkListStack();
}
return linkListStackObj;
}
/**
* 入栈
* @param obj 将要入栈的实例
*/
public synchronized void push(final Object obj) {
linkedList.add(obj);
}
/**
* 出栈
* @return linkedList 出栈的实例
*/
public synchronized Object pop() {
return linkedList.removeLast();
}
}
LinkedList list = new LinkedList(); public void push(Object x) {
synchronized(list) {
list.addLast( x );
list.notify();
}
} public Object pop()
throws Exception {
synchronized(list) {
if( list.size() <= 0 ) {
list.wait();
}
return list.removeLast();
}
}
}
我有一疑问,还请解答:wait() 是当前线程释放其占有的对象锁(是释放所有对象锁吗?),让其它线程得以使用这些对象;其本身进入锁等待状态
notity() 激活线程的锁等待,使其持有锁,以便运行另外,你的答复:
----
这个时候他获得2个锁,一个是Stack对象的锁,还有list对象的锁,而notify,释放的是stack对象的锁,没有释放list对象的锁
------
那个notify 应该wait吗,还是就是notify
谢谢
wait() 是等待指定对象,释放获得的指定对象的锁,所以调用哪个对象的wait方法,就等待哪个对象并释放拥有的那个对象的锁。具体怎么改8楼已经帮你改好了,能用么?
A中对象条件不满足时,wait; 等待B改变了该对象的条件,并notify,A接着执行以上正确不?
while(!condition) {
obj.wait();} obj.doSomething(); }
当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。 在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A: synchronized(obj) {
condition = true; obj.notify(); }
需要注意的概念是: # 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {...} 代码段内。 # 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {...} 代码段内唤醒A。 # 当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。 # 如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。 # obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。 # 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。