wait异常

java.lang.IllegalMonitorStateException异常

private boolean wait = false;

public boolean pleaseWait() {
synchronized (this.wait) {
    if (this.wait == true) {
        return false;
    }

    this.wait =true;
    
    try {
        this.wait.wait();
    } catch (InterruptedException e) {

    }

    return true;
}

在调用wait()或者notify()之前,必须使用synchronized语义绑定住被wait/notify的对象。

可问题是,在上面的代码中,已经对this.wait这个变量使用了synchronzied,然后才调用的this.wait.wait()。按理不应该抛出这个异常。


真正的问题在于this.wait这个变量是一个Boolean,并且,在调用this.wait.wait()之前,this.wait执行了一次赋值操作
this.wait = true;

Boolean型变量在执行赋值语句的时候,其实是创建了一个新的对象。简单的说,在赋值语句的之前和之后,this.wait并不是同一个对象。
synchronzied(this.wait)绑定的是旧的Boolean对象,而this.wait.wait()使用的是新的Boolean对象。由于新的Boolean对象并没有使用synchronzied进行同步,所以系统抛出了IllegalMonitorStateException异常。
相同的悲剧还有可能出现在this.wait是Integer或者String类型的时候。
一个解决方案是采用java.util.concurrent.atomic中对应的类型,比如这里就应该是AtomicBoolean。采用AtomicBoolean类型,可以保证对它的修改不会产生新的对象。
正确的代码:

private AtomicBoolean wait = new AtomicBoolean(false);  
  
public boolean pleaseWait() {  
    synchronized (this.wait) {  
        if (this.wait.get() == true) {  
            return false;  
        }  
  
        this.wait.set(true);  
  
        try {  
            this.wait.wait();  
        } catch (InterruptedException e) {  
  
        }  
  
        return true;  
    }  
}

 

posted @ 2017-10-26 09:00  牧 天  阅读(338)  评论(0)    收藏  举报