关于Boolean类型做为同步锁异常问题

public class Test2 {
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> volatile Boolean aBoolean = <span class="hljs-keyword">true</span>;
<span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span> <span class="hljs-inheritance"><span class="hljs-keyword">implements</span></span> <span class="hljs-title">Runnable</span>{</span>
    @Override
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> run() {
        synchronized (aBoolean){
            <span class="hljs-keyword">while</span> (aBoolean){
                <span class="hljs-keyword">try</span> {
                    System.out.println(<span class="hljs-string">"进入A, 等待中"</span>);
                    aBoolean.wait();
                } <span class="hljs-keyword">catch</span> (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(<span class="hljs-string">"A over"</span>);
        }
    }
}

<span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">B</span> <span class="hljs-inheritance"><span class="hljs-keyword">implements</span></span> <span class="hljs-title">Runnable</span>{</span>

    @Override
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> run() {

        <span class="hljs-keyword">try</span> {
            TimeUnit.SECONDS.sleep(<span class="hljs-number">3</span>);
        } <span class="hljs-keyword">catch</span> (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (aBoolean){
            System.out.println(<span class="hljs-string">"通知A可以运行了"</span>);
            aBoolean = <span class="hljs-keyword">false</span>;
            aBoolean.notifyAll(); 
            <span class="hljs-comment">//Boolean.TRUE.notifyAll();</span>
        }
    }
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> main(String[] args) {
    <span class="hljs-keyword">new</span> Thread(<span class="hljs-keyword">new</span> A()).start();
    <span class="hljs-keyword">new</span> Thread(<span class="hljs-keyword">new</span> B()).start();
}

}

运行结果:

进入A, 等待中
通知A可以运行了
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at Test2$B.run(Test2.java:39)
    at java.lang.Thread.run(Thread.java:748)
由于我们会给aBoolean重新赋值, 导致对象监视器改变, 因为falsetrue这两个常量对应着两个不同的对象。当aBoolean产生变化时,很可能导致不同的线程同步了不同的对象
解决方法: 
将这一行 aBoolean.notifyAll();  改为: Boolean.TRUE.notifyAll();
或者是用显示锁ReentrantLock的方式
posted @ 2018-09-10 15:42  星朝  阅读(533)  评论(0编辑  收藏  举报