multithreading 什么是线程争用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1970345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 01:06:12  来源:igfitidea点击:

What is thread contention?

multithreadinglanguage-agnostic

提问by Tony The Lion

Can someone please explain simply what thread contention is?

有人可以简单解释一下什么是线程争用吗?

I have googled it, but cannot seem to find a simple explanation.

我用谷歌搜索过,但似乎找不到简单的解释。

采纳答案by keyboardP

Essentially thread contention is a condition where one thread is waiting for a lock/object that is currently being held by another thread. Therefore, this waiting thread cannot use that object until the other thread has unlocked that particular object.

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

回答by David Schwartz

Several answers seem to focus on lock contention, but locks are not the only resources on which contention can be experienced. Contention is simply when two threads try to access either the same resource or related resources in such a way that at least one of the contending threads runs more slowly than it would if the other thread(s) were not running.

几个答案似乎都集中在锁争用上,但锁并不是唯一可能发生争用的资源。争用只是当两个线程尝试以这样一种方式访问​​相同资源或相关资源时,至少一个竞争线程的运行速度比其他线程未运行时的运行速度慢。

The most obvious example of contention is on a lock. If thread A has a lock and thread B wants to acquire that same lock, thread B will have to wait until thread A releases the lock.

最明显的争用例子是锁。如果线程 A 有一个锁,而线程 B 想要获取相同的锁,则线程 B 将不得不等待线程 A 释放锁。

Now, this is platform-specific, but the thread may experience slowdowns even if it never has to wait for the other thread to release the lock! This is because a lock protects some kind of data, and the data itself will often be contended as well.

现在,这是特定于平台的,但线程可能会遇到减速,即使它永远不必等待另一个线程释放锁!这是因为锁保护了某种数据,而数据本身也经常被争用。

For example, consider a thread that acquires a lock, modifies an object, then releases the lock and does some other things. If two threads are doing this, even if they never fight for the lock, the threads may run much slower than they would if only one thread was running.

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

Why? Say each thread is running on its own core on a modern x86 CPU and the cores don't share an L2 cache. With just one thread, the object may remain in the L2 cache most of the time. With both threads running, each time one thread modifies the object, the other thread will find the data is not in its L2 cache because the other CPU invalidated the cache line. On a Pentium D, for example, this will cause the code to run at FSB speed, which is much less than L2 cache speed.

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

Since contention can occur even if the lock doesn't itself get contended for, contention can also occur when there is no lock. For example, say your CPU supports an atomic increment of a 32-bit variable. If one thread keeps incrementing and decrementing a variable, the variable will be hot in the cache much of the time. If two threads do it, their caches will contend for ownership of the memory holding that variable, and many accesses will be slower as the cache coherency protocol operates to secure each core ownership of the cache line.

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

Ironically, locks typically reducecontention. Why? Because without a lock, two threads could operate on the same object or collection and cause lots of contention (for example, there are lock free queues). Locks will tend to deschedule contending threads, allowing non-contending threads to run instead. If thread A holds a lock and thread B wants that same lock, the implementation can run thread C instead. If thread C doesn't need that lock, then future contention between threads A and B can be avoided for awhile. (Of course, this assumes there are other threads that could run. It won't help if the only way the system as a whole can make useful progress is by running threads that contend.)

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

回答by Jon B

From here:

这里

A contention occurs when a thread is waiting for a resource that is not readily available; it slows the execution of your code, but can clear up over time.

A deadlock occurs when a thread is waiting for a resource that a second thread has locked, and the second thread is waiting for a resource that the first thread has locked. More than two threads can be involved in a deadlock. A deadlock never resolves itself. It often causes the whole application, or the part that is experiencing the deadlock, to halt.

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

当一个线程正在等待第二个线程已锁定的资源,而第二个线程正在等待第一个线程已锁定的资源时,就会发生死锁。一个死锁可能涉及两个以上的线程。僵局永远不会自行解决。它通常会导致整个应用程序或遇到死锁的部分停止。

回答by Dave Black

I think there should be some clarification from the OP on the background of the question - I can think of 2 answers (though I'm sure there are additions to this list):

我认为 OP 应该对问题的背景进行一些澄清 - 我可以想到 2 个答案(尽管我确定此列表中还有其他内容):

  1. if you are referring to the general "concept" of thread contention and how it can present itself in an application, I defer to @DavidSchwartz's detailed answer above.

  2. There is also the '.NET CLR Locks and Threads:Total # of Contentions' Performance Counter. As taken from PerfMon description for this counter, it is defined as:

    This counter displays the total number of times threads in the CLR have attempted to acquire a managed lock unsuccessfully. Managed locks can be acquired in many ways; by the "lock" statement in C# or by calling System.Monitor.Enter or by using MethodImplOptions.Synchronized custom attribute.

  1. 如果您指的是线程争用的一般“概念”以及它如何在应用程序中呈现,我将参考上面@DavidSchwartz 的详细回答。

  2. 还有'.NET CLR Locks and Threads:Total # of Contentions'性能计数器。根据此计数器的 PerfMon 描述,它被定义为:

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

...and I'm sure others for other OS'es and application frameworks.

...我相信其他操作系统和应用程序框架的其他人。

回答by Aaron M

You have 2 threads. Thread A and Thread B, you also have object C.

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

A is currently accessing object C, and has placed a lock on that object. B needs to access object C, but cannot do so until A releases the lock on object C.

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

回答by Mark Wilkins

Another word might be concurrency. It is simply the idea of two or more threads trying to use the same resource.

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

回答by Maciej

To me contention is a competition between 2 or more threads over a shared resource. Resource can be a lock, a counter etc. Competition means "who gets it first". The more threads the more contention. The more frequent access to a resource the more contention.

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

回答by snr

Imagine the following scenario. You are preparing for tomorrow's final examine and feel a little hungry. So, you give your younger brother ten bucks and ask him to buy a pizza for you. In this case, you are the main thread and your brother is a child thread. Once your order is given, both you and your brother are doing their job concurrently (i.e., studying and buying a pizza). Now, we have two cases to consider. First, your brother brings your pizza back and terminates while you are studying. In this case, you can stop studying and enjoy the pizza. Second, you finish your study early and sleep (i.e., your assigned job for today - study for tomorrow's final exam - is done) before the pizza is available. Of course, you cannot sleep; otherwise, you won't have a chance to eat the pizza. What you are going to do is to wait until your brother brings the pizza back.

想象一下下面的场景。你正在准备明天的期末考试,感觉有点饿。所以,你给你弟弟十块钱,让他给你买一个披萨。在这种情况下,您是主线程,您的兄弟是子线程。一旦您下订单,您和您的兄弟就会同时做他们的工作(即学习和购买比萨饼)。现在,我们有两种情况需要考虑。首先,你的兄弟把你的披萨拿回来,并在你学习时终止。在这种情况下,您可以停止学习并享用比萨饼。其次,你早点完成你的学习并在比萨可用之前睡觉(即你今天分配的工作——为明天的期末考试而学习——已经完成)。当然,你不能睡觉;否则,你将没有机会吃披萨。

As in the example, the two cases give meaning of rivalry.

如本例所示,这两种情况都具有竞争的含义。

回答by amilamad

Thread contention is also affect by I/O operations. Example when a Thread waiting for file read it can consider as a contention. Use I/O completion ports as solution.

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

回答by AndreyT

Lock contention takes place when a thread tries to acquire the lock to an object which is already acquired by other thread*. Until the object is released, the thread is blocked (in other words, it is in the Waiting state). In some cases, this may lead to a so-called serial execution which negatively affects application.

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

from dotTrace documentation

来自dotTrace 文档