为什么主要顺序中没有呼叫?

我正在阅读一本关于线程/同步的简单示例,该书声称使用synchronized将允许在同一实例上调用一个线程来访问该方法。 它确实按照承诺进行了序列化,但似乎在下面的Synch main方法中创建的第三个Caller大约9/10倍出现在第二个之前。 此代码是示例代码,显示没有同步方法的问题。

 class CallMe { void call(String msg) { System.out.print("[" + msg); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("CallMe 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(); } @Override public void run() { target.call(msg); } } class Synch { public static void main(String args[]) { CallMe target = new CallMe(); Caller c1 = new Caller(target, "Hello"); Caller c2 = new Caller(target, "Synchronized"); Caller c3 = new Caller(target, "World"); try { c1.t.join(); c2.t.join(); c3.t.join(); } catch (InterruptedException e) { System.out.println("Synch Interrupted"); } } } 

这本书展示了处理这个问题的两种方法,它们是 –
synchronized void call(String msg) {...}
public void run() { synchronized (target) {...} }

很明显,这两个选项都有效,因为与原始代码相反,括号内的单词与…一致。

[你好]
[世界](大约90%的时间是呼叫倒退)
[已同步](1 /多个已同步为第一个消息)

……原始代码没有押韵或理由。 所以我知道它“正在工作”,可以通过在每个Caller实例上放置断点来直接看到它。 当我这样做时,它显然对我来说很有效。

为什么第三个Caller在第二个call之前始终呼叫call

根据定义,线程并行运行,并且没有一个优先于任何其他线程。

一旦线程全部启动,它基本上是随机的,它将首先运行,一般来说,第一个启动将有一个轻微的“先发制人”,但与启动线程等的开销相比,先发制人是微不足道的。

你的特定环境的怪癖恰好偏向于一个线程,结果可能在不同的系统上有所不同,当然不应该依赖。

顺便提一下,这是一种不好的做法,原因有很多:

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

(你可能实际上有一个编译器警告)。

更好的是提供一种启动方法

 public Caller start() { t.start(); return this; } 

然后呢

 new Caller(target, msg).start(); 

这绝对可以确保Caller对象在Thread开始处理之前已完全初始化并准备就绪。

为什么第三个呼叫在第二个呼叫之前始终呼叫呼叫?

它不是这样做的 – 它大约90%的时间是这样做的。

基本上,同步不能保证先进先出……并且无法保证呼叫甚至会按照您期望的顺序进行。 三个新线程正在快速连续启动 – 无法保证哪个线程实际上会首先开始执行其代码。

从根本上说,如果要对并行代码进行排序,则需要明确地这样做。 同步不提供排序 – 它只提供排他性。

它确实按照承诺进行了序列化,但似乎在下面的Synch主方法中创建的第三个Caller大约9/10倍出现在第二个之前。

小心理解句子中“序列化”的含义:它意味着同一个锁保护的所有代码段永远不会并行运行 ; 换句话说,他们的执行将是连续的

并不意味着“执行这些代码部分将以严格的指定顺序进行”。 它不会。