異常IllegalMonitorStateException

    今天的一段代碼拋出了java.lang.IllegalMonitorStateException,代碼如下:

class ThreadC implements Runnable{
    Boolean falg;
    public ThreadC(Boolean falg) {
        this.falg = falg;
    }

    @Override
    public void run() {
        synchronized (falg){
            for (int i = 1; i <= 1000; i++) {
                if(i % 2 == 0 && i % 3 == 0 && i % 5 == 0 && i % 7 ==0){
                    try {
                        falg = true;//報錯的地方
                        System.out.println(i+"睡眠!");

                        falg.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                falg.notify();
            }
        }
    }
}

    上網查了很久,終於找到了答案:

    真正的問題在於falg這個變量是一個Boolean

    falg = true;
    Boolean型變量在執行賦值語句的時候,其實是創建了一個新的對象。簡單的說,在賦值語句的之前和之後,falg並不是同一個對象。
synchronzied(falg)綁定的是舊的Boolean對象,而重新賦值後新的Boolean對象並沒有使用synchronzied進行同步,所以系統拋出了IllegalMonitorStateException異常。

    相同的悲劇還有可能出現在falg是Integer或者String類型的時候。

    一個解決方案是採用java.util.concurrent.atomic中對應的類型,比如這裏就應該是AtomicBoolean。採用AtomicBoolean類型,可以保證對它的修改不會產生新的對象。

正確的代碼:

class ThreadC implements Runnable{
    AtomicBoolean falg;
    public ThreadC(AtomicBoolean falg) {
        this.falg = falg;
    }

    @Override
    public void run() {
        synchronized (falg) {
            for (int i = 1; i <= 1000; i++) {
                if (i % 2 == 0 && i % 3 == 0 && i % 5 == 0 && i % 7 == 0) {
                    try {
                        falg.set(true);
                        System.out.println(i + "睡眠!");

                        falg.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
               falg.notify();
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章