问题描述
也许我想表达的不是那么清楚,
第一种情况是关于何时以及如何使用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; } }});
就这样,我一直在 println 里找原因 我找到了真正的原因
public void println(String x) { synchronized (this) { print(x); newLine(); } }
同步导致线程切换
而且有了开关,线程的缓冲区就清零了,
所以线程2读取一个新值