日常小结-while多线程改变判断条件时的异常情况

时间:2022-10-31 13:25:49

昨天写程序遇到一个坑,花了很久才找到是为什么。以往程序出错主要还是自身原因,这算是第一个类似bug的存在。这做下记录。

本来是希望写一个检测标志位的程序,因为耗时很短,我就简单的写了个while循环去检测。结果程序在调试状态下很好的运行,但是直接运行就不行。

后来发现while循环似乎做了一些优化。如果while后面不加任何语句而直接以分号结尾,则程序检测一段时间后就不在继续检测了(类似挂起,但具体是不是挂起还有待研究)。如果是在多线程情况下while的判断语句必须加volatile否则程序会卡在while循环这里。

这里写个简单的demo来说明一下这个问题:

public class Test {


    public static void main(String[] args) throws InterruptedException {
        A a = new A();
        a.start();
        System.out.println(a.flag);
// Thread.sleep(10); //不加延时会正常运行
        System.out.println(a.flag);
        a.flag=true;
    }
}
    class A extends Thread{
    boolean flag;//加上volatile则4种情况都可以正常运行
    public A(){
        flag = false;
    }
    public boolean isFlag() {
        return flag;
    }
    @Override
    public void run(){
// while(!isFlag());//无法正常运行
// while(!flag);//无法正常运行
// while(!isFlag())System.out.println("pass");;//正常运行
// while(!flag)System.out.println("pass");//正常运行
        System.out.println("finish");
    }
}

这里讨论了四种情况,首先这种异常的情况只有在一个线程使用while检测标志位并且,直接以分好结尾,而使用第二个线程改变while循环的判断条件的时候才出现,而且第二个线程如果在一定时限内改变则可以正常运行,只有在第一个线程进行while判断一段时间后(这里是10ms)之后再进行改变,则第一个线程会卡在while循环处不能正常运行。

出现的情况和while循环的判断语句无关。

解决的方案目前发现两种,一种是while不直接加分号,而是进行一些操作,则不会出现异常情况。另一种是使用volatile标志位。

目前还不清楚出现这样情况的原因。不过这样的情况最好还是用waitnotify的方法来做比较好

运行环境:
操作系统:Ubuntu 14.04
IDE:myeclipse 2014.
JRE:java1.7


update 2016.11.23
现在想来应该是内存可见性问题。并不是什么bug。。我二逼了。。