【问题标题】:Problem about shared variable between threads in Java(11)Java中线程间共享变量的问题(11)
【发布时间】:2020-12-26 09:59:00
【问题描述】:

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

启动后,除非使用volatile,否则主线程不会发现flag的变化

但是,在示例中,意外地,thread2 得到了 flag 的变化,为什么会发生这种情况?

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

【问题讨论】:

  • 老实说我不明白你的问题,但让我澄清一些事情。为了让变量在 Java 中的多个线程之间(实时)共享其状态,它需要是 Volatile。使用静态变量:它们在线程之间共享,但在一个线程中所做的更改可能不会立即对另一个线程可见,这使得变量看起来像是有两个副本。 stackoverflow.com/questions/13582395/…xspdf.com/resolution/52087767.html
  • 对不起,可能我希望表达的不是那么清楚,第一个案例是关于何时以及如何使用volatile的示例,为了让程序成功运行,我们需要添加挥发性的。第二个是希望表达,即使没有 volatile,程序也能成功运行。我希望知道为什么在没有“volatile”的情况下会发生这种情况
  • 实际上,@SusanMustafa - 严格来说,它需要 volatile 并不完全正确。还有其他方法。例如,适当地使用synchronized,或使用AtomicXxx 类型,或使用final 字段。
  • @StephenC 是的斯蒂芬,也许我的评论可能会让人觉得这是唯一的方法,但是我确实给出了一个示例 stackoverflow 以进行更多说明。
  • @StephenC hhh,谢谢,感觉很好:P

标签: java thread-safety volatile


【解决方案1】:

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

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 读取了一个新值

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-28
    • 2019-05-01
    • 2023-03-04
    • 1970-01-01
    • 2021-08-12
    • 2019-01-28
    • 2017-07-22
    • 1970-01-01
    相关资源
    最近更新 更多