java.lang.IllegalMonitorStateException:(m = null)无法获取监视器

And*_*ich 36 java multithreading locking pool

为什么会这样?问题是监视器对象肯定不是null,但我们仍然经常得到这个异常:

java.lang.IllegalMonitorStateException: (m=null) Failed to get monitor for (tIdx=60)
        at java.lang.Object.wait(Object.java:474)
        at ...
Run Code Online (Sandbox Code Playgroud)

引发这种情况的代码是一个简单的池解决方案:

    public Object takeObject() {
        Object obj = internalTakeObject();
        while (obj == null) {
            try {
                available.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            obj = internalTakeObject();
        }
        return obj;
    }

    private Object internalTakeObject() {
        Object obj = null;
        synchronized (available) {
            if (available.size() > 0) {
                obj = available.keySet().iterator().next();
                available.remove(obj);
                synchronized (taken) {
                    taken.put(obj, Boolean.valueOf(true));
                }
            }
        }
        return obj;
    }

    public void returnObject(Object obj) {
        synchronized (taken) {
            taken.remove(obj);
        }
        synchronized (available) {
            if (available.size() < size) {
                available.put(obj, Boolean.valueOf(true));
                available.notify();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?

编辑:异常发生available.wait();在行.

tgd*_*ies 72

请参阅Object.wait的javadoc.

特别是"当前线程必须拥有此对象的监视器".和"[throws] IllegalMonitorStateException - 如果当前线程不是对象监视器的所有者." 也就是说,您需要在要调用的对象上进行同步等待.

所以你的代码应该是:

synchronized (available) {
    available.wait();
}
Run Code Online (Sandbox Code Playgroud)

  • 值得知道:如果在`available.notify()`上发生此异常,请使用相同的模式. (5认同)

Mau*_*rry 7

available.wait(); 必须在同步(可用)部分