1

I have this class, which is a basic approach to a file locking utility (doesn't interact with the locks from the OS tho). The idea is to have a static HashMap which stores pair of references to File objects that are used by the application with binary semaphores. Upon first access to a new file the pair is stored into the variable. The problem is that the .wait() line throws IllegalMonitorStateException, and I can't understand why, because I've created a project to test this class with only one thread, so it's impossible that the thread accessing the method doesn't own the object, isn't it?

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();
    }
}

My intention was that the methods weren't synchronized, but since I started receiving this exception, I changed them to synchronized so they theoretically make sure that the thread entering them owns the resources used, but it's not working, the same exception arises.

Exception trace: Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:503)
at org.lsp.io.files.FileLocker.getLock(FileLocker.java:18)
at org.lsp.main.Main.main(Main.java:9)

Called with

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

1 回答 1

6

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

应该

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

wait在这种情况下正在等待对象监视器。由于您没有在信号量上同步,即:

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

你得到你的例外。由acquireSemaphore 提供并为您处理同步。

注意你也会遇到同样的情况,notify()而不是release()

于 2013-12-03T20:10:00.743 回答