那个IllegalMonitorStateException ......线程没有拥有该对象?不可能,只有一个

时间:2013-12-03 19:40:37

标签: java multithreading semaphore illegalmonitorstateexcep

我有这个类,这是文件锁定实用程序的基本方法(不与来自OS的锁相互作用)。我们的想法是拥有一个静态HashMap,它存储对应用程序使用二进制信号量的File对象的一对引用。首次访问新文件时,该对存储在变量中。 问题是.wait()行抛出了IllegalMonitorStateException,我无法理解为什么,因为我创建了一个只用一个线程来测试这个类的项目,所以访问该方法的线程不可能拥有对象,不是吗?

public abstract class FileLocker {

    private static final HashMap<File, Semaphore> locksMap = new HashMap<>();

    public synchronized static final void getLock(final File file) {
        if (!FileLocker.locksMap.containsKey(file)) {
            FileLocker.locksMap.put(file, new Semaphore(1, Boolean.TRUE));
        }
        try {
            FileLocker.locksMap.get(file).wait();
        } catch (final InterruptedException e) {
            SysLogger.log(e, "ERR0", SysLogger.Level.CRASH);
        }
        if (file.isDirectory()) {
            for (final File f : file.listFiles()) {
                if (f.isDirectory()) {
                    FileLocker.getLock(f);
                }
            }
        }
    }

    public synchronized static final void releaseLock(final File file) {
        if (file.isDirectory()) {
            for (final File f : file.listFiles()) {
                if (f.isDirectory()) {
                FileLocker.releaseLock(f);
                } else {
                FileLocker.locksMap.get(file).notify();
                }
            }
        }
        FileLocker.locksMap.get(file).notify();
    }
}

我的意图是方法没有同步,但是因为我开始接收这个异常,我把它们改为同步所以他们理论上确保进入它们的线程拥有所使用的资源,但它不起作用,同样的例外就产生了。

异常追踪: 线程“main”中的异常java.lang.IllegalMonitorStateException
    在java.lang.Object.wait(Native方法)
    在java.lang.Object.wait(Object.java:503)
    在org.lsp.io.files.FileLocker.getLock(FileLocker.java:18)
    在org.lsp.main.Main.main(Main.java:9)

调用
FileLocker.getLock(Paths.get("default.xml").toFile());

1 个答案:

答案 0 :(得分:6)

FileLocker.locksMap.get(file).wait();

应该是

FileLocker.locksMap.get(file).acquire();

在这种情况下,

wait正在等待对象监视器。由于你没有在信号量上同步,即:

Semaphore s = FileLocker.locksMap.get(file);
synchronized(s){
     s.wait();
}

你得到了例外。 acquire由Semaphore提供,并为您处理同步。

注意您也会遇到与notify()而非release()

相同的情况