Java中线程间共享变量的问题11

问题描述

也许我想表达的不是那么清楚, 第一种情况是关于何时以及如何使用volatile的示例,并且为了使程序成功运行,我们需要添加volatile。

第二个是希望表示,即使没有 volatile,程序也能成功运行。 我希望知道为什么会在没有“volatile”的情况下发生这种情况

在第一个示例中,使用 volatile 的典型示例

public static int num=1;

public static class MyThread extends Thread {
    // flag
    private boolean flag = false ;
    public boolean isFlag() { return flag;}
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) { e.printstacktrace();
        }
// change flag to true
        this.flag = true ;
        System.out.println("flag=" + flag);
        this.flag=true;
    }
}
// main
static void testWithOutVolatile(){
    MyThread t=new MyThread();
    t.start();
    while(true) {
        boolean is=t.flag;
        if (is) {
            System.out.println("run======");
        }
    }
}
@H_502_11@

启动后,主线程不会发现标志的变化,除非使用 volatile

然而,在示例中,线程2意外得到了标志的变化,为什么会发生这种情况?

static int amb=0;
static void testSimple(){
    Thread t1=new Thread(()->{
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printstacktrace();
        }
        amb++;
    });
    Thread t2=new Thread(()->{while(true) {
        if (amb == 0) {
            System.out.println("no");
        }
        if (amb != 0) {
            System.out.println("SUc");
            break;
        }
    }});
    t2.start();
    t1.start();
}
@H_502_11@

尝试后,我发现我是否删除代码

if (amb == 0) {
            System.out.println("no");
        }
@H_502_11@

它会像我想的那样运行,thread2 无法获得更改。

感谢您的回答,QwQ

解决方法

可能是, 第二种情况,io语句刷新Thread的缓冲区

Thread t2=new Thread(()->{while(true) {
        System.out.println("no");
        if (amb != 0) {
            System.out.println("SUc");
            break;
        }
    }});

如果我使用 io 语句(Sout),它将成功运行。 results of using io

就这样,我一直在 println 里找原因 我找到了真正的原因

 public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

同步导致线程切换

而且有了开关,线程的缓冲区就清零了,

所以线程2读取一个新值