Java Thread Ping Pong示例问题

时间:2015-02-09 04:20:11

标签: java multithreading synchronize

我已经看过使用synchronized关键字的PingPong示例。基本上,实际的例子是:

public class PingPong implements Runnable {

    synchronized void hit(long n) throws InterruptedException {

        for (int i = 1; i < 3; i++)
            System.out.print(n + "-" + i + " ");
    }

    public static void main(String[] args) {
        new Thread(new PingPong()).start();
        new Thread(new PingPong()).start();
    }

    public void run() {
        try {
            Long id = Thread.currentThread().getId();

            hit(id);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

通常命中方法不同步,因为只有当有一个对象时,synchronized关键字才有效。所以结果可以是8-1 9-1 8-2 9-2或8-1 9-1 9- 2 8-2 ......(这是随机的结果)。但是在这个例子中它给我们所有的时间8-1 8-2 9-1 9-2这有点奇怪,因为这意味着命中方法同步!!! 我已修改代码以再次检查命中方法必须不是sycnhronized,所以我在命中方法的开头添加一个Thread.sleep(1000)就像

synchronized void hit(long n) throws InterruptedException {
        Thread.sleep(1000);
        for (int i = 1; i < 3; i++)
            System.out.print(n + "-" + i + " ");
    }

现在代码每次执行都会给出随机结果。

我真的很困惑! 有人可以帮助我理解这个问题吗?

2 个答案:

答案 0 :(得分:2)

你确实有两个单独的PingPong实例,这意味着会有两个独立的监视器对象,这意味着线程不会被强制同步运行。

我认为您可能正在遇到线程调度行为。在单核CPU上,代码可以很好地执行,因为线程调度程序永远不会有机会接管。

如果你为你的for循环添加一个睡眠:

synchronized void hit(long n) throws InterruptedException {

    for (int i = 1; i < 3; i++){
        System.out.print(n + "-" + i + " ");
        Thread.sleep(0);
    }
}

那应该释放调度程序来运行其他线程。请注意,JVM并不能保证调度程序的实际行为,但根据我的经验,上述内容就足够了。

如果您使用的是多核CPU,我希望它能够在没有sleep()电话的情况下按预期工作。

答案 1 :(得分:1)

不确定同步的含义。您是否想要线程调度程序以特定顺序拾取线程?如果是的话,那不是真的。只是增加&#34;我&#34;从3到更高的值,比如10.我看到以下输出:

12-1 11-1 12-2 11-2 12-3 11-3 12-4 11-4 12-5 11-5 12-6 11-6 12-7 11-7 12- 8 12-9 11-8 11-9

好吧,我有多核处理器,因此在同一时间点有多个线程。我想即使对你来说也应如此。