论述题 6.  下面这段代码在一些特定的情况下有问题,请指出并改正。
    import java.util.List;
    import java.util.ArrayList;
    public class MyStack
    {
    private List<String>stack=new ArrayList<String>();
    public synchronized void push(String value)
    {
    synchronized(this)
    {
    stack.add(value);
    notify();
    }
    }
    public synchronized String pop() throws InterruptedException
    {
    synchronized(this)
    {
    if(stack.size()<=0)
    {
    wait();
    }
    return stack.remove(stack.size()-1);
    }
    }
    }
【正确答案】以上这段代码在大部分情况下都能正常运行,但在下面的场景中会有问题:
   在多线程访问这个栈的时候,如果有三个线程按照如下的顺序访问,问题就会暴露。
   1)线程1先执行pop操作,此时,由于list的大小为0,因此,会调用wait释放等待锁。
   2)线程2执行push操作,往队列里放了一个元素,这个线程会调用notify来唤醒等待的线程。
   3)就在此时恰好另外一个线程3也执行pop操作,那么线程1和线程3的执行顺序是无法保证的。如果恰好线程3先执行pop操作,执行完成后,线程2被唤醒,此时线程2会执行returnstack.remove(stack.size()-1)操作,由于此时队列已经为空,stack.size()的返回值为0,所以,程序会抛出java.lang.ArrayIndexOutOfBoundsException异常。
   以上问题的解决方法也很简单,即在pop操作调用remove方法前再进行一次判断,判断列表里是否还有元素,实现代码如下:
   public synchronized String pop()throws IntermptedException
   {
   synchronized(this)
   {
   if(stack.size()<=0)
   {
   wait();
   }
   if(stack.size()<=0)
   return null;
   else
   return stack.remove(stack.size()-1);
   }
【答案解析】