这个Java程序可以打印除零以外的值吗?

时间:2011-09-27 22:19:19

标签: java multithreading

我有一个最喜欢的C#程序,类似于下面的程序,它表明如果两个线程共享相同的内存地址进行计数(一个线程递增n次,一个线程递减n次),你可以获得非零的最终结果。只要n相当大,就很容易让C#在[-n,n]之间显示一些非零值。但是,即使将线程数增加到1000(500 up,500 down),我也无法让Java产生非零结果。是否有一些内存模型或规格差异与C#我不知道保证这个程序总是会产生0,尽管我不知道调度或核心数量?我们是否同意即使我们无法通过实验证明该程序也能产生非零值?

(不是:,我在here上找到了这个确切的问题,但是当我运行该主题的代码时,我也得到零。)

public class Counter
{
  private int _counter = 0;

  Counter() throws Exception
  {
    final int limit = Integer.MAX_VALUE;

    Thread add = new Thread()
    {
      public void run()
      {
        for(int i = 0; i<limit; i++)
        {
          _counter++;
        }
      }
    };

    Thread sub = new Thread()
    {
      public void run()
      {
        for(int i = 0; i<limit; i++)
        {
         _counter--;
        }
      }
    };

    add.run();
    sub.run();
    add.join();
    sub.join();

    System.out.println(_counter);
  }

  public static void main(String[] args) throws Exception
  {
    new Counter();
  }
}

3 个答案:

答案 0 :(得分:4)

您给出的代码只在单个线程上运行,因此总是会得到0的结果。如果您实际上启动两个线程,您确实可以获得非零结果:< / p>

// Don't call run(), which is a synchronous call, which doesn't start any threads
// Call start(), which starts a new thread and calls run() *in that thread*.
add.start();
sub.start();

在试运行中我的盒子上给了-2146200243。

答案 1 :(得分:2)

假设你真的是start,而不是run

在大多数常见平台上,它很可能会产生非零,因为++ / --在多核的情况下不是原子操作。在单核/单CPU上,您很可能会得到0因为++ / --是原子的,如果编译为一条指令(add / inc),但该部分依赖于JVM

在此处查看结果:http://ideone.com/IzTT2

答案 2 :(得分:0)

您的程序存在的问题是您没有创建OS线程,因此您的程序基本上是单线程的。在Java中,您必须调用Thread.start()来创建新的OS线程,而不是Thread.run()。这与初始Java API中令人遗憾的错误有关。这个错误是设计师让Thread实现了Runnable

add.start();
sub.start();
add.join();
sub.join();