1
public class newTest{

/**
 * @param args
 */
public static Integer x = new Integer(0);

public static void main(String[] args) {
    newTest tstobj = new newTest();
    // TODO Auto-generated method stub
    MyThread t = tstobj.new MyThread();
    t.start();
    tstobj.incrementX();
    System.out.println(x.intValue());
    try {
        t.join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

public synchronized void incrementX(){
    try {
        while(x != 5){
            x.wait();
        }
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}



public class MyThread extends Thread{
    newTest tstobj = new newTest();
    public void run() {
        // TODO Auto-generated method stub      
        tstobj.incrementX();
    }
}

}

我不确定为什么这段代码会导致 IllegalMonitorStateException 而不是无限循环。具体来说,这段代码有两个线程 1. 主线程 2. MyThread 他们都尝试调用名为 incrementX() 的同步方法,所以假设两个线程中的一个通过获取锁进入同步方法,然后它看到 x ! = 5 所以它调用 wait 将释放锁并将被放置在等待队列中,等待调用同步方法的下一个线程将通过获取锁进入并看到 x != 5 并调用 wait 将挂起线程并放入等待队列。现在两个线程在等待队列中什么都不做,这应该会导致一个无限循环。但是这段代码会导致非法MonitorStateException?

这段代码不会做任何有用的事情,但我想了解我在概念上哪里出错了?我查看了很多材料,但仍然无法弄清楚我对代码的期望有什么问题。任何帮助都会很棒。谢谢

4

2 回答 2

2

只需将您的wait电话更改为: -

wait();  // or `this.wait()

您只能在已锁定的对象上调用wait和方法。notify因此,当您调用该synchronized方法时,您实际上将锁定引用指向的对象this。因此,您需要wait()this引用时调用。

wait使用和方法时,您可以遵循以下两条规则notify:-

  • 同步方法总是锁定this引用。
  • 同步块可以锁定任何引用,具体取决于括号中使用的对象引用。

示例(同步块):-

synchonized(obj) {    // Locks `obj`
    obj.wait();       // Invoke wait on obj
}
于 2012-12-02T14:14:35.260 回答
0

要首先调用wait()某个对象,您必须获得该对象的锁定。所以首先

synchronize(x){

    //some code

    x.wait();

}
于 2012-12-02T14:16:21.967 回答