用synchronized块替换volatile不起作用

时间:2015-04-01 07:50:51

标签: java multithreading thread-safety

我正在阅读this教程。我理解volatile关键字的用法。但是当我试图在不使用volatile关键字的情况下在同步块中对关注变量进行操作时实现相同的结果时,它不起作用。它抛出IllegalMonitorStateException。这是我试过的修改后的代码。

public class VolatileTest {
private static Integer MY_INT = 0;

public static void main(String[] args) {
    new ChangeListener().start();
    new ChangeMaker().start();
}

static class ChangeListener extends Thread {
    @Override
    public void run() {
         synchronized(MY_INT){
        int local_value = MY_INT;
        while ( local_value < 5){
            if( local_value!= MY_INT){
                System.out.format("Got Change for MY_INT : {0}", MY_INT);
                 local_value= MY_INT; 
                  try {
                MY_INT.wait();
            } catch (Exception e) { e.printStackTrace(); }}
            }
        }
    }
}

static class ChangeMaker extends Thread{
    @Override
    public void run() {
         synchronized(MY_INT){
        int local_value = MY_INT;
        while (MY_INT <5){
            System.out.format("Incrementing MY_INT to {0}", local_value+1);
            MY_INT = ++local_value;
            try {
                MY_INT.notify();
            } catch (Exception e) { e.printStackTrace(); }
        }
    }
}}}

我想知道的是,在这种情况下,可以使用synchronized块替换volatile,如果是,那么该怎么做? 感谢。

1 个答案:

答案 0 :(得分:6)

问题在于:

 MY_INT = ++local_value;

MY_INT是一个Integer变量,当您为其指定一个新值时,您在此处锁定的对象:

 synchronized(MY_INT){

将与您在此处通知的对象不同:

  MY_INT.notify();

......这将导致例外。


解决方案是制作锁定对象static final。显然这意味着你无法分配......但这就是重点!