【问题标题】:Multithreading "unpredictable" behavior [duplicate]多线程“不可预测”的行为[重复]
【发布时间】:2016-05-09 11:25:47
【问题描述】:

我正在浏览 volatile 的用例,我遇到了以下情况:

private static boolean stop = false;
public static void main(String[] args) throws InterruptedException {
    Thread runner = new Thread(new Runnable() {

        @Override
        public void run() {
            int i = 0;
            long start = System.currentTimeMillis();
            while(!stop){
                i++;
            }
            System.out.println("I m done after "+(System.currentTimeMillis() - start));
        }
    });

    runner.start();
    Thread.sleep(2000);
    stop = true;
}

上面的代码无限期地运行。这很好,因为编译器为了优化代码而进行了提升。但是,如果我将 i++ 替换为其他一些语句,例如System.out.println("Hello")。 2 秒后停止。

为什么会有这样的行为?我正在使用 jdk1.7.0_51。

注意: 我知道我应该将 stop 声明为 volatile。但是,我想知道上述情况下行为的原因。

【问题讨论】:

  • 从蹩脚的角度来看,增加值比写入流更容易。 :)。
  • 我能想到的一个原因是 i++ 被转换为不使用 I/O 的 Java 字节码,而 System.out.println 实际上是 I/O。这可能会给您足够的时间来查看布尔变量的变化

标签: java multithreading


【解决方案1】:

标准输出是跨线程的共享资源。 Java 的PrintStream 类使用同步块实现线程安全,并且所有同步块都是java 中的内存屏障,这就是为什么stop 字段的更改在循环内变得可见的原因。但是,您不应该依赖这个。

例如,看看PrintStream.println 的实现:

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

【讨论】:

    猜你喜欢
    • 2012-12-28
    • 2012-03-28
    • 2017-12-06
    • 2019-04-16
    • 2017-09-09
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多