什么是线程争用?

有人可以请简单地解释什么线程争用?

我GOOGLE了,但似乎无法find一个简单的解释。

本质上,线程争用是一个线程正在等待当前被另一个线程持有的锁/对象的情况。 因此,这个等待线程不能使用该对象,直到另一个线程已经解锁该特定对象。

好几个答案似乎都集中在锁争用上,但是锁并不是可以体验竞争的唯一资源。 当两个线程尝试访问相同资源或相关资源时,竞争就是这样:至less有一个竞争线程运行得比其他线程不运行时要慢。

竞争最明显的例子就是locking。 如果线程A有一个锁并且线程B想获得同一个锁,线程B将不得不等待线程A释放锁。

现在,这是特定于平台的,但即使不需要等待另一个线程释放锁,线程也可能会变慢。 这是因为一个锁可以保护某种数据,而数据本身通常也会被争夺。

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

为什么? 假设每个线程都在现代x86 CPU上运行在自己的内核上,并且内核不共享L2caching。 只有一个线程,对象可能大部分时间都保留在二级caching中。 在两个线程都在运行时,每当一个线程修改对象时,另一个线程就会发现数据不在其L2caching中,因为另一个CPU使caching线无效。 例如,在Pentium D上,这将导致代码以FSB速度运行,这比L2高速caching速度低得多。

由于即使锁本身没有争用也可能发生争用,所以当没有锁时也可能发生争用。 例如,假设你的CPU支持一个32位variables的primefaces增量。 如果一个线程继续递增和递减一个variables,那么这个variables在大部分时间里都会在caching中变热。 如果两个线程这样做,他们的高速caching将争夺拥有该variables的内存的所有权,并且由于高速caching一致性协议操作以保护高速caching线的每个核心所有权,所以许多访问将会较慢。

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

从这里 :

当线程正在等待不可用的资源时发生争用; 它减慢了代码的执行速度,但可以随着时间的推移而清除。

当线程正在等待第二个线程已被locking的资源时,会发生死锁,并且第二个线程正在等待第一个线程已locking的资源。 死锁可能涉及两个以上的线程。 死锁决不会自行解决。 它通常会导致整个应用程序或正在经历僵局的部分停止。

你有2个线程。 线程A和线程B,还有对象C.

A当前正在访问对象C,并在该对象上放置了一个锁。 B需要访问对象C,但不能这样做,直到A释放对象C上的locking

我认为这个问题的背景应该有一些说明 – 我可以想到2个答案(虽然我确信这个列表中还有其他内容):

  1. 如果您提到的是线程争用的一般“概念”,以及它如何在应用程序中呈现出来,那么我将遵循@DavidSchwartz在上面的详细解答。

  2. 还有“.NET CLR锁和线程:争用总数”性能计数器。 从该计数器的PerfMon描述中可以看出,它被定义为:

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

…我确信其他OS和应用程序框架。

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

对我来说,争夺是一个共享资源上的2个或更multithreading之间的竞争。 资源可以是锁,柜台等。竞争意味着“谁先得到”。 线程越多,争用越多。 对资源的访问越频繁,竞争越激烈。

线程争用也受I / O操作的影响。 当一个等待文件的线程读取它的例子可以考虑作为一个争用。 使用I / O完成端口作为解决scheme。

当一个线程试图获取一个已经被其他线程获取的对象的锁时,会发生锁争用。 直到对象被释放,线程被阻塞(换句话说,它处于等待状态)。 在某些情况下,这可能会导致所谓的串行执行,这会对应用程序产生负面影响。

来自dotTrace文档

想象下面的情况。 你正在准备明天的最后检查,感觉有点饿了。 所以,你给你的弟弟十块钱,并要求他为你买一个披萨。 在这种情况下,你是主线程,你的兄弟是一个子线程。 一旦你的订单被给出,你和你的兄弟都在同时工作(即学习和购买比萨饼)。 现在我们有两个案例需要考虑。 首先,你的兄弟把你的比萨带回来,在你学习的时候终止。 在这种情况下,你可以停止学习和享受披萨。 其次,在披萨可用之前,您尽早完成学习和睡眠(即,今天指定的工作 – 明天期末考试的学习)。 当然,你睡不着; 否则,你将没有机会吃披萨。 你要做的是等到你的兄弟把比萨带回来。

正如在这个例子中,这两个案例给出了竞争的意义。