Multithreading “为什么?”;锁是一种昂贵的操作。”;这么频繁地说出来?
我已经阅读了很多关于线程和所有同步机制的资料。我也理解做得不好的危险 我刚刚看了PDC2009关于并行性和并发性的视频,这里再次提到“锁是一个昂贵的操作”。我现在在各种文本和书籍中都遇到过这样一个短语,我也听过这个领域的专家这么说 我想知道,获得一个锁(互斥或信号量)到底有什么代价?它是否导致在汇编程序级别发出Multithreading “为什么?”;锁是一种昂贵的操作。”;这么频繁地说出来?,multithreading,performance,synchronization,Multithreading,Performance,Synchronization,我已经阅读了很多关于线程和所有同步机制的资料。我也理解做得不好的危险 我刚刚看了PDC2009关于并行性和并发性的视频,这里再次提到“锁是一个昂贵的操作”。我现在在各种文本和书籍中都遇到过这样一个短语,我也听过这个领域的专家这么说 我想知道,获得一个锁(互斥或信号量)到底有什么代价?它是否导致在汇编程序级别发出LOCK 35;指令 获取锁是否需要对操作系统进行内核调用 为什么锁被认为是一种昂贵的操作?“昂贵”是一个相当相对的术语,因此如果我们将其与创建新线程(需要设置线程堆栈等)进行比较,那么获
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)
语句很昂贵,而是阻塞其他线程的行为很昂贵,并且只应该在您认为值得花费的情况下进行
*当然,如果在单线程应用程序中发生锁争用,它将永远不会结束。
当可变共享数据需要锁时,您可能会失去并行性的好处。
让我们首先简化一下,上下文切换是免费的,锁是便宜的(这两个都不完全正确-我们将在最后讨论这些问题)
- 考虑一下线程不共享数据的情况:线程可以运行 独立地而不必担心其他线程的状态。拥有两个线程将使算法运行速度提高一倍
- 接下来,介绍一些随时间变化的共享数据。 根据定义,任何两个线程都不能同时修改/读取此数据 同时。这意味着如果两个线程碰巧想要访问 对于这些数据,您不再有并发操作:它们必须在 序列化(同步)方式。这种情况越频繁 发生争用时,应用程序的行为越像 单线程应用程序优于双线程应用程序