java线程间共享变量问题(11)

nwnhqdif  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(331)

也许我希望表达的不是那么清楚,第一个案例是关于何时使用和如何使用的示例 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======");
        }
    }
}

启动后,除非使用volatile,否则主线程将找不到标志的更改
但是,在示例中,thread2意外地更改了标志,为什么会发生这种情况?

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();
}

在尝试之后,我发现如果我删除了代码

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

它会像我想的那样运行,thread2无法获得更改。
谢谢你的回答,qwq

57hvy0tb

57hvy0tb1#

在第二种情况下,可能是io语句刷新线程的缓冲区

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

如果我使用io语句(sout),它将成功工作。

就这样,我不断在println中寻找原因,我找到了真正的原因

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

同步导致线程切换
有了这个开关,线程的缓冲区很清晰,
所以thread2读取一个新值

相关问题