【问题标题】:Strange java concurrency behavior [closed]奇怪的java并发行为[关闭]
【发布时间】:2014-11-25 17:57:16
【问题描述】:

我有以下代码:

class Hi
{
   public static void main (String [] args)
   {
      int a = 1;
      for (int i = 0; i < 50; i++) {
          a = a + i;
          System.out.println ("a before sleep is " + a);
          try {
              Thread.sleep(4000);
          } catch (InterruptedException e) {

          }
          System.out.println ("a after sleep is " + a);
      }
   }
}

我打开两个控制台窗口并在第一个窗口中执行java Hi。然后等待大约 10 秒,然后在第二个窗口中执行相同操作。两个输出是一样的:

a before sleep is 1
a after sleep is 1
a before sleep is 2
a after sleep is 2
a before sleep is 4
a after sleep is 4
a before sleep is 7
a after sleep is 7
a before sleep is 11
a after sleep is 11

没有交错。那么,如果我什至不费心使用synchronized 语句,并发问题会引起什么轰动呢?是不是因为从不同控制台窗口运行的代码在不同的处理器内核上执行?如果是这样,我已经进行了大约 20 次这个实验,结果还是一样。

【问题讨论】:

  • 我不明白。你预计会发生什么?
  • 所以你正在运行 2 个不同的程序?
  • 请注意,即使您确实有多个线程,局部变量通常仍然不会共享。如果您启动两个线程,并且两个线程都调用 mainProcess 方法,并且该方法有一个局部变量(如您的示例中的 a),则每个方法仍然有自己的该变量的副本,并且不会有并发问题。
  • @ajb:虽然如果两个变量引用同一个object,你又可以共享了。 (不过与int 之类的原语无关。)
  • 两者在不同的JVM中

标签: java concurrency


【解决方案1】:

我打开两个控制台窗口并在第一个窗口中执行 java Hi。然后等待大约 10 秒,然后在第二个窗口中执行相同操作。

您正在启动两个完全独立的过程。这根本没有使用多线程——每个进程都有自己的变量、自己的输出,以及一切。

要查看多线程,您需要在单个进程中创建线程。例如:

import java.util.Random;

class Counter implements Runnable {
    private int a;

    public void run() {
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            String name = Thread.currentThread().getName();
            a++;
            System.out.println(name + " Before sleep, a = " + a);
            try {
                // Add a little more uncertainty...
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
                // Ignored
            }
            System.out.println(name + " After sleep, a = " + a);
        }
    }
}

public class ThreadingTest {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        Thread t1 = new Thread(counter);
        Thread t2 = new Thread(counter);
        t1.start();
        t2.start();
    }
}

【讨论】:

  • 开始注意到你无处不在:P
  • @Zapadlo 请注意,Jon 的示例将仅显示交错,因为 a 是公共对象中的实例字段,而不是 run 中的局部变量。
【解决方案2】:

您有两个不同的 JVM,因此两个主线程在两个不同的 JVM 上运行,因此并发性不适用。

是的,如果您在同一个 JVM 中有两个线程,则适用并发。

【讨论】:

    【解决方案3】:

    这是您计算机上的两个独立进程。他们不共享数据或其他任何东西。它们不再相关,例如,您的网络浏览器和您的文字处理器。他们每个人都有自己独立的“a”变量,每个变量都彼此完全无关。

    当同一进程空间中的多个线程尝试访问同一变量时,会出现并发问题。这不适用于这里。

    【讨论】:

      【解决方案4】:

      在这里,您正在运行两个不同的进程,无论您运行此代码多少次,您都会得到相同的结果。因为这两个程序都将在两个单独的进程中运行。

      要以多线程方式运行这些程序,您必须实现两个线程并启动它们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-03
        • 1970-01-01
        • 1970-01-01
        • 2016-02-16
        • 2017-01-02
        • 1970-01-01
        相关资源
        最近更新 更多