2010-07-29 42 views
11

保罗季马的presentation,我发现了一个面试问题:什么更难,同步2线程或1000线程?

什么困难,同步2个线程或同步线程的1000?

从我的角度来看,当然同步1000个线程比较困难,但我想不出有什么好的理由。但由于它的面试问题,可能是我错了(面试的问题必须是棘手的,不是吗?)。

+3

从JVM或程序员的角度? – 2010-07-29 12:51:51

+0

@Tim Buthe:不知道。我从幻灯片中复制了问题 – nanda 2010-07-29 12:54:00

回答

14

同步千线程就像同步两个线程一样简单:只需锁定对所有重要数据的访问。现在

,同步一千线程具有良好的性能是比较困难的。如果我问这个问题,我会寻找答案,提到“雷鸣群体问题”,“锁定争用”,“锁定实施可扩展性”,“避免自旋锁”等。

3

为什么同步1000个线程比同步2个线程困难?

将被添加的唯一代码是产生额外的线程。

你就不必添加任何同步码(只要你正确地做的一切)。

0

这同样困难。但是通过2个线程进行同步很可能会表现得更好,因为只有2个线程会同时在一个锁上而不是一千个,因为锁定的资源可能会导致更多的开销。

希望这有助于

3

我认为答案是,你必须同步两个线程毕竟其他的998也将同步

0

对象不同步线程。创建同步的方法或代码块可以防止多个线程同时执行该区域 - 因此,如果有2,1000或1,000,000个线程,则无关紧要。

就性能而言,如果您希望在线程数加倍的情况下实现双倍并行性(半执行时间),那么任何同步区域在性能方面将成为瓶颈,因为它本质上是串行代码这不能平行。

+0

由于线程是同步的,而不是对象。对象(或更确切地说,连接到它们的监视器)是实现它的手段,但目标是协调(“同步”)执行代码的线程。 – 2010-07-29 14:16:02

+0

@Michael Borgwardt:这一切都取决于“同步”的意思,但通常我会说ACTIONS是需要同步的。大多数操作都涉及在某个对象上运行的THREAD。如果两个线程正在做完全独立的事情,那么没有办法完全“同步”它们。虽然两个相关的对象可能被描述为彼此“同步”或“不同步”,但我不认为这就是最初提出的问题。 – supercat 2010-07-29 14:26:09

1

这是唯一真正的答案是“它取决于”的问题之一。在这种情况下,这取决于你在做什么。

情景可能是作为一个后台工作线程简单的前台等待,同时显示进度表。或者它可以产生1000个线程,并在做其他事情之前等待它们全部完成。

可选地,如果少至2线程访问共享资源,则该概念是相同的。对于并发性问题和锁定策略,无论是2还是1000,都必须非常小心。无论多于多少个线程,都不能保证别的东西不会尝试同时读取或写入到您所在的相同资源。

38

您可以使2个线程正确同步的情况实际上比1000个更难,因为如果您有竞争条件,它通常会以1000个线程快速显示,但只有2个不会显示。

但在另一方面,同步1000线,而不会在锁争用问题是当只有有比更难2.

真正的答案是“同步线程是很难以各种方式,期限。”

+3

+1“如果你有一个竞争条件,它通常会以1000个线程快速显示,但只有2个线程会显示非常快。”对我而言这是关键 - 但也许不是最明显的答案。 – 2010-07-29 13:49:18

+1

很好玩,先生。打的好。 – 2010-07-29 13:52:46

0

如果您使用像Scala这样的编程语言来设计Actors模式,那么您不必同步任何东西。 http://www.scala-lang.org/node/242

另一种选择(在Java中)是使用比较和交换/设置机制http://en.wikipedia.org/wiki/Compare-and-swap,所以你不必同步任何线程,因为它们是你正在比较和读取的原子变量(非阻塞)并且只能根据您的解决方案阻止/等待写入,从而获得一些巨大的性能提升

+0

这并非完全正确。我喜欢斯卡拉,但仍然存在共享有限资源的问题。也就是说,只能有这么多的套接字,写入/读取给定文件的人等。 – wheaties 2010-07-29 13:08:27

+1

我真的很喜欢Compare-And-Swap;我想知道为什么我没有看到它推动更多。更令人感兴趣的是我在白皮书中看到的一个2级条件加载原语,该原语在硬件中应该切实可行,并且可以实现实际的双重比较和交换。 DCAS允许非常实用的无锁数据结构。由于我讨厌锁定,我认为一个实际的DCAS会非常有用。 – supercat 2010-07-29 14:28:23

3

这取决于“更容易”的含义。设计/锁定机制的复杂性大致相同。

这就是说,我认为1000线程程序可能更容易debug。脆弱的种族条件发生的概率较高,并可能更容易复制。如果月亮已满并且您正在度假,两条线索中的竞赛条件可能只会每5年出现一次。

+1

更容易复制但难以解决? – nanda 2010-07-29 13:10:31

+2

困难的部分是弄清楚它存在问题,它是什么以及它在哪里。能够可靠地复制错误条件使问题更容易解决。 – jdizzle 2010-07-29 13:56:51

+0

+1“你正在度假”* g – Daniel 2011-03-04 20:03:41

1

我同意那些陈述“取决于”的说法。如果线程是相同的,那么2和1000线程之间的差别不会那么大。但是,如果有多个资源需要互斥访问(以Java术语同步),则随着线程数量的增加,死锁的可能性可能会增加。

3

我有两个答案。

  1. CASE 1:利用现有资源:同步2个线程是相同的困难,因为由于现有的用于同步的线程的任意数量的创建同步1000个线程。
  2. 案例2:从零开始实施似乎很明显,如果您必须从头开始实施同步系统,那么构建2线程系统会更容易。
+3

我同意。有了两个线程,资源分配非常简单;当一个线程完成一个资源时,另一个线程获取它。饥饿和优先倒置不是问题。对于三个或更多线程,需要注意防止饥饿(对于在其他线程中传递的资源,线程会无休止地等待)。如果实施优先级,则优先级反转也可能是一个问题(等待低优先级线程占用资源的最大优先级线程,而中等优先级线程占用CPU)。那些只有两个线程是非问题。 – supercat 2010-07-29 14:33:59

2

带读写器问题。使用两个线程,您可以使用互斥并完成。随着更多的线程,你必须写非平凡的代码,因为否则读者不能同时阅读,或者更糟的是,他们可能会扼杀作家。

但是,良好的同步代码应该适用于任意数量的线程。在某些情况下,比如互斥,你可以添加Java的同步关键字,并且对于2个线程来说就像1000一样困难。

换句话说,如果你的程序只使用2个线程,你可以利用它并做出假设这对于更多的线程来说是不正确的。显然这不是一个好习惯,但它是可能的。

4

在一次采访中,我会说“恰好两个线程”是一个非常有用的多线程特例。像饥饿和优先级倒置这样的事情可能发生在最少三个线程的情况下,但只有两个线程优先级反转和饥饿永远不会发生(当然,如果一个线程释放并重新获得一个锁而不让另一个线程启动,即使在可用时立即抓住锁,也可能发生三个线程饥饿)。从2线程到3线比从3线到1000线更大。

1

当我浏览你的答案时,我发现了几个有趣的内容。我认为,在采访中,这比答案更重要:转换,严格。