Java中的同步代码输出顺序错误

时间:2014-03-23 12:41:00

标签: java synchronization

我目前正在学习Java,我已经达到了同步的主题。

由于某些原因,下面的代码(基于完整参考JAVA - Herbert Schildt第7版,第239-240页中的代码)不能提供所需的输出。

代码:

package package1;
class Call{
    synchronized public void call(String msg){
        System.out.print("[" + msg);
        try{
            Thread.sleep(100);
        }catch (InterruptedException e){
            System.out.println("Interrupted Exception Caught");
        }
        System.out.println("]");
    }
}

class CallMe implements Runnable{
    String msg;
    Call target;
    Thread t;

    public CallMe(Call targ, String message){
        target = targ;
        msg = message;
        t = new Thread(this);
        t.start();
    }

    public void run(){
        target.call(msg);
    }
}

public class Synchronization {
    public static void main(String[] args) {
        Call target = new Call();
        CallMe obj1 = new CallMe(target, "Hello");
        CallMe obj2 = new CallMe(target, "Synchronized");
        CallMe obj3 = new CallMe(target, "World");

        try{
            obj1.t.join();
            obj2.t.join();
            obj3.t.join();
        }catch (InterruptedException e){
            System.out.println("Interrupted Exception Caught");
        }
    }
}

所需的输出:

[Hello]
[Synchronized]
[World]

实际输出(我在Macbook Pro 2013年末使用Eclipse):

[Hello]
[World]
[Synchronized]

我已经读过所有这些主题的输出因计算机而异。

有人可以解释一下,为什么这不起作用?

2 个答案:

答案 0 :(得分:3)

因为并行调用了不同的CallMe实例,并且您无法保证它们的处理顺序。您唯一知道的是,Call.call(String)并未同时调用,因为此方法为synchronized

答案 1 :(得分:0)

稍微回顾彼得的回答。所有的同步都可以防止事情变得疯狂。

在没有同步调用的情况下尝试此代码,您可以看到调用类可以随意命中.out而不考虑其他对象。我得到这样的输出,用" synchronized"删除:

[Hello[World[Synchronized]
]
]

通过同步,您可以得到类似于您所看到的内容,但它并不能保证订单。有时你得到:

[Hello]
[World]
[Synchronized] 

有时你得到:

[Hello]
[Synchronized]
[World]

一遍又一遍地运行它你会明白我的意思 要真正抛弃它尝试使用:

Thread.sleep(1);