1

大家好,我有这个代码:

public class ThreadTester {
    public static void main(String args[]) {
        Counter c = new Counter();
        for (int i = 0; i < 10; i++) {
            MyThread a = new MyThread(c);
            MyThread b = new MyThread(c);
            a.start();
            b.start();
        }   
        System.out.println("The value of the balance is " + c.getVal());
    }
}

class MyThread extends Thread {
    private Counter c;
    public MyThread(Counter c){ this.c = c; }
    public void run(){ s.increment(); }
}

class Counter {
    private int i = 100;
    public synchronized void increment(){ i++; }
    public synchronized int getVal(){ return i; }
}

现在我认为这应该给出 120 的期望结果 - 但是结果似乎在 115 和 120 之间波动。如果我在Thread.sleep(1)之后添加一个,b.start()我总是得到 120 的期望结果。为什么会发生这种情况?

这真的让我很困惑,如果能得到任何帮助,我将不胜感激,谢谢

4

5 回答 5

3

您在启动所有线程后打印计数器的值,而不是在所有线程完成后打印。

在您开始等待的所有线程上使用 Thread.join() 直到它们完成,然后打印该值。或使用 CountDownLatch。睡眠会意外地为您提供正确的结果。它允许所有线程完成,但只是因为它们要做的事情太少,睡 1 毫秒就足够了。

于 2013-05-10T20:45:20.917 回答
1

因为线程并行运行。

c.getVal()在您的一个或多个其他线程增加主线程之前,您正在主线程中打印。

当你睡觉时,你让其他线程有足够的时间完成,然后打印。

于 2013-05-10T20:45:09.857 回答
0

您可能在线程完成之前打印结果(这就是结果不同的原因)。您需要等到所有线程都完成后才能打印结果。

重组你的main方法如下:

public static void main(String args[]) {
    Counter c = new Counter();
    MyThread[] a = MyThread[20];
    for (int i = 0; i < 20; i++) {
        a[i] = new MyThread(c);
        a[i].start();
    }
    for (int i = 0; i < 20; i++) {
        a[i].join();        
    }
    System.out.println("The value of the balance is " + c.getVal());
}

首先,我循环了 20 次,因为你的循环在创建两个线程时迭代了 10 次(所以你也创建了 20 个线程)。您需要保留引用(通过a数组),以便主线程可以等到所有线程都完成(使用join)。当它们都完成后,返回正确的结果。

于 2013-05-12T10:50:22.670 回答
0

原因:

第三个线程(执行main())函数在以随机顺序启动线程 a 和 b 后立即进入以下语句,这就是您得到不可预测结果的原因。

    System.out.println("The value of the balance is " + c.getVal());

下一个问题:

如果我在 b.start() 之后添加一个 Thread.sleep(1),我总是得到 120 的预期结果。为什么会发生这种情况?

发生这种情况是因为您停止主线程足够长的时间(1 秒在 CPU 世界中是很长的时间)以允许线程 a 和 b 完成。

解决方案:让主线程等待,直到线程 a 和 b 都完成。单程:

    Counter c = new Counter();
    for (int i = 0; i < 10; i++) {
        MyThread a = new MyThread(c);
        MyThread b = new MyThread(c);
        a.start();
        b.start();
    }   
    a.join(); // wait for thread a to finish
    b.join(); // wait for thread b to finish

    System.out.println("The value of the balance is " + c.getVal());
于 2013-05-12T04:55:12.640 回答
0

因为在您到达 System.out 时,并非所有线程都完成了它们的增量任务。注入睡眠允许线程在到达输出之前完成。

于 2013-05-10T20:48:04.223 回答