Java 这个堆栈类有一些多线程问题?
我有一个堆栈类,像这样Java 这个堆栈类有一些多线程问题?,java,multithreading,Java,Multithreading,我有一个堆栈类,像这样 public class Stack { LinkedList list = new LinkedList(); public synchronized void push(Object x) { synchronized (list) { list.addLast(x); notify(); } } public synchronized Object
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();
}
}
}
公共类堆栈{
LinkedList=新建LinkedList();
公共同步无效推送(对象x){
已同步(列表){
列表。addLast(x);
通知();
}
}
公共同步对象pop()引发异常{
已同步(列表){
if(list.size()
是否有一些多线程问题导致堆栈崩溃
将来,您应该始终提供异常详细信息,以便我们能够更好地或至少定义“崩溃”的含义,并提供日志输出。在这种情况下,我怀疑您得到了一个NoTouchElementException
// we use while here to protect against the race condition
while (list.size() <= 0) {
wait();
}
return list.removeLast();
您的代码缺少一个小但关键的更改
synchronized (list) {
// here's your problem, if should be while
if (list.size() <= 0) {
wait();
}
return list.removeLast();
}
通过使用while
,一旦thread-A获得锁,它就可以重新检查以确保另一个线程没有从堆栈中“窃取”通知它的项。有关此争用条件的更多详细信息,请参阅my
其他几点意见:
- 您不需要
同步
方法和列表
上的同步
块。我建议只删除方法上的同步
关键字,除非您没有显示其他代码,只需在列表
上同步。然后您应该执行列表。等待()
列表
字段应该是private
和final
,如果线程程序中的已同步
,则建议使用这两个字段
错误是什么?为什么要在两个对象上同步两次?您最好执行以下操作:将列表设置为私有,并删除内部已同步的块。此外,最好将通知()
替换为notifyAll()
并在一个周期内调用等待()
,以避免与以下内容相关的错误唤醒: