为什么这个简单的Java同步代码块示例根据我锁定的对象给出不同的输出?

为什么这个简单的Java同步代码块示例根据我锁定的对象给出不同的输出?,java,multithreading,locking,Java,Multithreading,Locking,好的,我正在尝试学习多线程。我正在读一本书,遇到了以下同步代码块示例: class CallMe { void call(String msg) { System.out.print("[" + msg); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Interrupted")

好的,我正在尝试学习多线程。我正在读一本书,遇到了以下同步代码块示例:

class CallMe {
    void call(String msg) {
        System.out.print("[" + msg);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            System.out.println("Interrupted");
        }
        System.out.println("]");
    }
}

class Caller implements Runnable {

    String msg;
    CallMe target;
    Thread t;

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

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

public class Scrap {
    public static void main(String[] args) {
        CallMe target = new CallMe();
        Caller ob1 = new Caller( target, "Hello");
        Caller ob2 = new Caller( target, "Synchronized" );
        Caller ob3 = new Caller( target, "World");

        try {
            ob1.t.join();
            ob2.t.join();
            ob3.t.join();
        } catch (Exception e) {
            System.out.println("Interrupted");
        }
    }
}
我从中获得了以下输出:

[Hello]
[World]
[Synchronized]
然后,因为我在网上做了一些教程,我知道创建
Object
的实例只是为了锁定是一种很好的方式(或者被告知这一点)。因此,我这样做了,
调用者
类变成:

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

    private Object lock = new Object();

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

    public void run() {
        synchronized (lock) {
            target.call(msg);
        }
    }
}
当我将此作为输出时,我有点惊讶:

[Synchronized[Hello[World]
]
]

当然,这是发生了交织的输出,它是不正确的。我的问题是为什么会发生这种情况?我认为制作锁
对象将得到相同的结果。为什么它(或者为什么它会)不给我同样的输出?我认为创建
对象
实例是一种很好的风格,在这种情况下也会如此,老实说,我不明白为什么在“target”和“lock”上锁定会有所不同。我想我想问的是,为什么在这种情况下锁定一个特定项目会导致程序正确,而锁定另一个项目则会导致程序错误?

调用方的每个实例
都会锁定另一个
实例。我认为您必须对共享实例进行
同步
。将
锁定
静态
成员将在所有线程中共享同一实例。

同步
取决于目标对象。是,但是在这种情况下有什么不同呢?我首先要批评本教程,说
可运行的
不应该在
线程中启动自己。调用方的每个
实例都锁定在
锁的不同实例上。我认为您必须对共享实例进行
同步
。使对象锁定为静态。说“静态”而不是“共享”,我认为您赢得了这个问题。:)@mttdbrd不要将事物
设置为静态
,只是为了让您可以共享它们。如果需要,可以传入相同的参数。当然,但是我们有很多线程在单个对象上同步。为什么要把它传来传去做意大利面代码?如果只是传来传去,可能是在乞求僵局。@mttdbrd我没看到意大利面条。我看到了一个实例字段,重要的是它必须是所有线程中的同一个实例。