2013-12-03 31 views
1

我有這個類,這是一個文件鎖定實用程序的基本方法(不與來自OS tho的鎖進行交互)。這個想法是有一個靜態HashMap,它存儲了一對應用程序使用二進制信號量的File對象的引用。在第一次訪問新文件時,該對被存儲到變量中。 問題是.wait()行引發IllegalMonitorStateException,我不明白爲什麼,因爲我創建了一個項目來測試這個類只有一個線程,所以訪問該方法的線程不可能不會擁有物體,不是嗎?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(本機方法)
在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()); 
+0

我們需要看到調用代碼和堆棧跟蹤遇到了同樣的情況。 – chrylis

+1

這是一個常見問題。您在_object_實例上同步等待。可以有1000個同步塊但只有一個線程。 – Gray

+0

這些方法已經'同步'@Gray,所以它不是你想重複建議的問題。 –

回答

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

相關問題