代码之家  ›  专栏  ›  技术社区  ›  Tony The Lion

什么是线程争用?

  •  88
  • Tony The Lion  · 技术社区  · 15 年前

    有人能简单地解释什么是线程争用吗?

    我在谷歌上搜索过,但似乎找不到一个简单的解释。

    10 回复  |  直到 8 年前
        1
  •  63
  •   keyboardP    15 年前

    实际上,线程争用是一个线程正在等待另一个线程当前持有的锁/对象的情况。因此,在另一个线程解锁该特定对象之前,等待线程不能使用该对象。

        2
  •  153
  •   Yair Nevet    11 年前

    有几个答案似乎集中在锁争用上,但锁并不是唯一可以经历争用的资源。争用只是当两个线程试图访问同一资源或相关资源时,其中至少一个争用线程的运行速度比其他线程不运行时要慢。

    最明显的争用例子是锁上的争用。如果线程A有一个锁,而线程B想要获取相同的锁,那么线程B必须等待线程A释放锁。

    现在,这是特定于平台的,但是线程可能会经历慢运行,即使它从不需要等待另一个线程释放锁!这是因为锁保护某种类型的数据,而数据本身也经常受到挑战。

    例如,考虑一个获取锁、修改对象、然后释放锁并执行其他操作的线程。如果两个线程正在这样做,即使它们从未为锁而战,线程的运行速度可能比只有一个线程在运行时慢得多。

    为什么?假设每个线程在一个现代x86 CPU上运行在自己的内核上,而内核不共享二级缓存。如果只有一个线程,对象大部分时间可能会保留在二级缓存中。当两个线程都运行时,每次一个线程修改对象时,另一个线程都会发现数据不在其二级缓存中,因为另一个CPU使缓存线无效。例如,在奔腾D上,这将导致代码以fsb速度运行,而fsb速度远低于二级缓存速度。

    因为即使锁本身没有被争用,争用也可能发生,所以当没有锁时,争用也可能发生。例如,假设您的CPU支持32位变量的原子增量。如果一个线程不断地递增和递减一个变量,那么该变量在缓存中的大部分时间都是热的。如果两个线程都这样做,那么它们的缓存将争夺持有该变量的内存的所有权,并且随着缓存一致性协议的运行来保护缓存线的每个核心所有权,许多访问将变慢。

    讽刺的是,锁通常 减少 争用。为什么?因为没有锁,两个线程可以在同一个对象或集合上操作,并导致大量争用(例如,存在无锁队列)。锁将倾向于重新安排争用线程的时间表,从而允许非争用线程运行。如果线程A持有锁,而线程B想要相同的锁,那么实现可以运行线程C。如果线程C不需要这个锁,那么可以暂时避免线程A和B之间将来的争用。(当然,这假设有其他线程可以运行。如果系统作为一个整体能够取得有用进展的唯一方法是运行争用的线程,那就没有帮助了。)

        3
  •  18
  •   Jon B    15 年前

    here :

    当一个线程 正在等待不是 随时可用;它减慢 执行代码,但可以清除 随着时间的推移。

    当线程 等待一个资源 线程已锁定,第二个线程 线程正在等待一个资源 第一个线程已锁定。超过 两个线程可以参与 死锁。死锁决不会解决。 本身。它常常导致整个 应用程序,或 经历死锁,停止。

        4
  •  3
  •   Dave Black    11 年前

    我认为OP应该对这个问题的背景做一些澄清-我可以考虑两个答案(尽管我确信这个列表中还有一些补充):

    1. 如果您提到线程争用的一般“概念”以及线程争用如何在应用程序中呈现自己,那么我遵从@davidschwartz上面的详细答案。

    2. 还有“.net clr locks and threads:total_of contentions”性能计数器。从这个计数器的PerfMon描述中,它被定义为:

      此计数器显示CLR中的线程尝试获取托管锁失败的总次数。托管锁可以通过多种方式获取:通过C中的“lock”语句、调用System.Monitor.Enter或使用MethodImplOptions.Synchronized自定义属性。

    …我相信其他操作系统和应用程序框架也有。

        5
  •  2
  •   Aaron M    15 年前

    你有两条线。线程A和线程B,也有对象C。

    a当前正在访问对象c,并已对该对象设置了锁。 B需要访问对象C,但在A释放对象C上的锁之前,不能这样做。

        6
  •  1
  •   Mark Wilkins    15 年前

    另一个词可能是并发。这只是两个或多个线程试图使用相同资源的想法。

        7
  •  1
  •   Maciej    13 年前

    对我来说,争用是两个或多个线程在共享资源上的竞争。资源可以是锁、计数器等。竞争意味着“谁先得到它”。线程越多,争用就越多。对资源的访问越频繁,争用就越多。

        8
  •  0
  •   amilamad    9 年前

    线程争用也会受到I/O操作的影响。例如,当等待文件读取的线程可以将其视为争用。使用I/O完成端口作为解决方案。

        9
  •  0
  •   AndreyT    9 年前

    当线程试图将锁获取到 已被其他线程*获取的对象。直到物体 被释放,线程被阻塞(换句话说,它在 等待状态)。在某些情况下,这可能导致所谓的串行 对应用程序有负面影响的执行。

    dotTrace documentation

        10
  •  0
  •   Soner from The Ottoman Empire    8 年前

    想象一下下面的场景。你正在为明天的决赛做准备 检查一下,感觉有点饿。所以,你给你弟弟 十块钱,让他给你买一个披萨。在这种情况下,你是 主线和你的兄弟是一个孩子线。一旦你的订单 既然,你和你弟弟都在同时工作 (即学习和购买比萨饼)。现在,我们有两个案子 考虑一下。首先,你哥哥把你的披萨拿回来并终止 在你学习的时候。在这种情况下,你可以停止学习并享受 比萨饼。第二,你早点完成学业,然后睡觉(也就是说, 今天的分配工作-明天期末考试的学习-完成) 在比萨饼上市之前。当然,你不能睡觉,否则, 你没有机会吃比萨饼。你要做的是 等你哥哥把披萨拿回来。

    就像在例子中一样,这两个例子给出了竞争的含义。