Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading “为什么?”;锁是一种昂贵的操作。”;这么频繁地说出来?_Multithreading_Performance_Synchronization - Fatal编程技术网

Multithreading “为什么?”;锁是一种昂贵的操作。”;这么频繁地说出来?

Multithreading “为什么?”;锁是一种昂贵的操作。”;这么频繁地说出来?,multithreading,performance,synchronization,Multithreading,Performance,Synchronization,我已经阅读了很多关于线程和所有同步机制的资料。我也理解做得不好的危险 我刚刚看了PDC2009关于并行性和并发性的视频,这里再次提到“锁是一个昂贵的操作”。我现在在各种文本和书籍中都遇到过这样一个短语,我也听过这个领域的专家这么说 我想知道,获得一个锁(互斥或信号量)到底有什么代价?它是否导致在汇编程序级别发出LOCK 35;指令 获取锁是否需要对操作系统进行内核调用 为什么锁被认为是一种昂贵的操作?“昂贵”是一个相当相对的术语,因此如果我们将其与创建新线程(需要设置线程堆栈等)进行比较,那么获

我已经阅读了很多关于线程和所有同步机制的资料。我也理解做得不好的危险

我刚刚看了PDC2009关于并行性和并发性的视频,这里再次提到“锁是一个昂贵的操作”。我现在在各种文本和书籍中都遇到过这样一个短语,我也听过这个领域的专家这么说

我想知道,获得一个锁(互斥或信号量)到底有什么代价?它是否导致在汇编程序级别发出
LOCK 35;
指令

获取锁是否需要对操作系统进行内核调用

为什么锁被认为是一种昂贵的操作?“昂贵”是一个相当相对的术语,因此如果我们将其与创建新线程(需要设置线程堆栈等)进行比较,那么获得锁的成本到底有多高

封面下面是什么

我的猜测是,它不可能那么昂贵,因为我确信Windows(例如)要运行,必须始终使用数百个锁/同步机制

有人能详细说明吗


注意:我只是好奇,我知道线程是如何工作的,我也不想做一些愚蠢的优化。

锁通常是旋转锁,这会导致线程在锁定时“旋转”而不做任何有用的工作


什么都不做是很昂贵的,因为众所周知:“时间就是金钱”。

锁很昂贵,因为它们会阻止其他线程获得锁。延迟可能是致命的,使多处理器系统比没有锁的单线程设计慢

它是否导致在汇编程序级别发出锁指令

不,因为它并不总是这样

获取锁是否需要对操作系统进行内核调用

不,因为它通常不会这样做

事实上,锁非常非常便宜。价格昂贵的是竞争。如果必须在锁和争用之间进行选择,大多数情况下锁是更好的选择

如果使用得当,锁是一种避免争用的机制。它们会自动找到争用的线程并取消对它们的调度,这样一来,主要是以不争用的线程并发运行结束

例如:假设您有四个线程准备运行,A、B、C和D。假设A和B相互竞争(假设它们操作同一个集合)。假设C和D相互竞争,但A不与C竞争。如果A和B同时运行(竞争),锁将导致其中一个未准备好运行,调度程序将调度C(或D),两个线程将运行,而不会进一步竞争。(至少在下一次上下文切换之前。)


通常,当人们说“锁是昂贵的”时,他们的意思是争用是昂贵的。不幸的是,通过这样的措辞,他们经常鼓励人们最小化锁,但在这个过程中增加争用。在绝大多数情况下,这是一个失败的主张。(有一些例外。)

简单的回答是:不,它们不贵

较长的答案是:是的,它们很昂贵,因为除非你的锁毫无意义,什么都不做,否则锁的存在会减慢你的代码

实际答案需要澄清:

技术vs.实施vs.设计:

Technical:answer澄清了这一点,即,如果您运行单线程代码,其中包含lock语句,那么锁不会降低您的速度*

实现:在his中指出,锁很慢,因为阻塞会导致延迟,从而导致应用程序速度变慢


设计:真正的答案是,包含锁的设计往往比不包含锁的设计慢。锁是用来降低代码速度的

因此,如果您能够合理地编写代码,使锁永远不会被命中或根本不需要,那么您绝对应该这样做。这就是人们说“锁很昂贵”的原因。这并不是因为
lock(obj)
语句很昂贵,而是阻塞其他线程的行为很昂贵,并且只应该在您认为值得花费的情况下进行

*当然,如果在单线程应用程序中发生锁争用,它将永远不会结束。

当可变共享数据需要锁时,您可能会失去并行性的好处。

让我们首先简化一下,上下文切换是免费的,锁是便宜的(这两个都不完全正确-我们将在最后讨论这些问题)

  • 考虑一下线程不共享数据的情况:线程可以运行 独立地而不必担心其他线程的状态。拥有两个线程将使算法运行速度提高一倍

  • 接下来,介绍一些随时间变化的共享数据。 根据定义,任何两个线程都不能同时修改/读取此数据 同时。这意味着如果两个线程碰巧想要访问 对于这些数据,您不再有并发操作:它们必须在 序列化(同步)方式。这种情况越频繁 发生争用时,应用程序的行为越像 单线程应用程序优于双线程应用程序

因此,当有人说“锁是一个昂贵的操作”时,我认为这是由于并行性的潜在损失,而不是锁本身的昂贵

成本 除了失去并行性之外,如果您积累了锁和潜在同步和上下文切换的小但非零成本,那么拥有锁很可能会降低算法的速度

还要注意的是,您尝试访问的线程越多