异常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();
            }
        }
    }
}
发布了30 篇原创文章 · 获赞 39 · 访问量 2055

猜你喜欢

转载自blog.csdn.net/weixin_44564242/article/details/105082202