关于自定义中断标记问题

MyRunnable2.java

public class MyRunnable2 implements Runnable{
    public boolean flag = true;
    int i = 0;
    public MyRunnable2() {
        flag = true;
    }
    @Override
    public void run() {
        while(flag) {
            System.out.println(Thread.currentThread().getName() +"=="+(i++) + flag);

            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }


    }

}






Test4.java

public class Test4 {
    public static void main(String[] args) {
        MyRunnable2 mr2 = new MyRunnable2();
        Thread t = new Thread(mr2);

        t.start();

        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName()+"-"+i);

            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if (i ==20) {
                mr2.flag = false;

            }

        }
    }

}

在Test4.java中,主线程for循环到i为20的时候 mr2.flag设置为false,这样就可以控制t进程不再进行

图片说明

但是它运行了,而且flag还是false,虽然后面t进程被中断了。
我想问的是:为什么flag为flase它还可以运行一次

那是因为该变量的值发生变化的时候,另一个线程并没有立即得到最新的值,就是并发编程中的数据失效问题。
把它定义为 public volatile boolan 类型的就可以了,它可以保证变量值立即被其他线程知晓。