为什么这个简单的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我没看到意大利面条。我看到了一个实例字段,重要的是它必须是所有线程中的同一个实例。