在run()方法中,为什么计数器是一个随机数?

时间:2014-12-20 03:28:16

标签: java multithreading

我不明白为什么计数器的输出每次都是一个不同的随机数。当我在run()方法中打印出计数器时,它每次都是100000,但是当我对该语句进行注释时,它会给出一个随机数。

    public class Answer extends Thread {
      private static int counter = 0;
      private static final int THREADS = 4;
      public static final int COUNT = 100000;
      public static void main(String[] args) {
         Answer[] threads = new Answer[THREADS];
         for (int i = 0; i < THREADS; i++) {
            threads[i] = new Answer();
            threads[i].start();
         }
         try {
            for (int i = 0; i < THREADS; i++) {
               threads[i].join();
            }
         } catch (InterruptedException e) {
            e.printStackTrace();
}
         System.out.println("Counter: " + counter);
      }
      public void run() {
         for (int i = 0; i < COUNT/THREADS; i++) {
             counter++; 
             //System.out.println(counter);
         }
} }

4 个答案:

答案 0 :(得分:1)

操作

 counter++
你的线程代码中的

不是线程安全的。你的主题正在踩着彼此的行动。

幸运的是,println的线程安全部分正在充分同步线程的操作,以防止静态变量的不利交互。当您注释掉println调用时,您将丢失该幸运同步。

如果您需要使用这样的东西进行制作,可以使用同步变量。

答案 1 :(得分:1)

以下两个原因。

  • 计数器++
  • 线程安排。

<强>计数器++

这不是线程安全的。

实施例。 计数器= 0。 线程1&amp;线程2尝试同时增加该值。两者都将从主存中获取值。线程内存增加。所以现在计数器是1.主内存更新为1而不是2。 您可以使用volatileAtomicInteger来解决此问题。

主题安排:

线程调度由OS完成。订单无法保证。即使您以相同的顺序提交thread1&amp; thread2&amp; thread3。它可能以不同的顺序运行。

答案 2 :(得分:0)

您的计数器变量是静态的,并且在您创建的所有线程之间共享,并且每个线程都在自行更改计数器。尝试删除&#39;静态&#39;来自计数器变量。

此:

private static int counter = 0;

对此:

private int counter = 0;

答案 3 :(得分:0)

counter是未受任何锁定或同步保护的线程之间的共享变量,因此各种线程上的counter++语句将以不可预测的方式“相互踩踏”。据推测,println引入了足够的延迟来抵消这种情况,尽管这不能保证100%。你有什么尝试来完成......?!