Ответы:
По сути, конкуренция потоков - это состояние, при котором один поток ожидает блокировки / объекта, который в настоящее время удерживается другим потоком. Следовательно, этот ожидающий поток не может использовать этот объект, пока другой поток не разблокирует этот конкретный объект.
Некоторые ответы, кажется, сосредоточены на конфликте блокировок, но блокировки - не единственные ресурсы, на которых может возникнуть конкуренция. Конфликт - это просто, когда два потока пытаются получить доступ к одному и тому же ресурсу или связанным ресурсам таким образом, что по крайней мере один из конкурирующих потоков работает медленнее, чем если бы другой поток (и) не работал.
Самый очевидный пример конфликта - блокировка. Если поток A имеет блокировку, а поток B хочет получить ту же самую блокировку, поток B должен будет ждать, пока поток A не освободит блокировку.
Теперь это зависит от платформы, но поток может замедляться, даже если ему никогда не придется ждать, пока другой поток освободит блокировку! Это связано с тем, что блокировка защищает некоторые данные, а сами данные также часто становятся предметом спора.
Например, рассмотрим поток, который получает блокировку, изменяет объект, затем снимает блокировку и выполняет некоторые другие действия. Если это делают два потока, даже если они никогда не борются за блокировку, потоки могут работать намного медленнее, чем если бы выполнялся только один поток.
Зачем? Скажем, каждый поток работает на своем собственном ядре на современном процессоре x86, а ядра не используют общий кеш L2. С помощью всего одного потока объект может оставаться в кэше L2 большую часть времени. Когда оба потока работают, каждый раз, когда один поток изменяет объект, другой поток обнаруживает, что данных нет в его кэше L2, потому что другой ЦП аннулировал строку кэша. Например, на Pentium D это приведет к тому, что код будет работать со скоростью FSB, которая намного меньше скорости кэш-памяти L2.
Поскольку конкуренция может возникать даже в том случае, если блокировка сама по себе не оспаривается, конкуренция может возникать и при отсутствии блокировки. Например, предположим, что ваш процессор поддерживает атомарное приращение 32-битной переменной. Если один поток продолжает увеличивать и уменьшать переменную, большую часть времени переменная будет находиться в кеше. Если это делают два потока, их кеш-память будет бороться за право владения памятью, содержащей эту переменную, и многие операции доступа будут медленнее, поскольку протокол согласованности кеш-памяти обеспечивает безопасность каждого ядра, владеющего строкой кэша.
Как ни странно, блокировки обычно уменьшают конкуренцию. Зачем? Поскольку без блокировки два потока могут работать с одним и тем же объектом или коллекцией и вызывать много конфликтов (например, есть очереди без блокировки). Блокировки будут стремиться исключить из расписания конкурирующие потоки, позволяя вместо этого запускать неконкурирующие потоки. Если поток A содержит блокировку, а поток B хочет такую же блокировку, реализация может вместо этого запустить поток C. Если потоку C не нужна эта блокировка, то будущего конфликта между потоками A и B можно избежать на некоторое время. (Конечно, это предполагает, что есть другие потоки, которые могут выполняться. Это не поможет, если единственный способ, которым система в целом может добиться полезного прогресса, - это запуск потоков, которые конкурируют.)
От сюда :
Конкуренция возникает, когда поток ожидает ресурс, который недоступен; это замедляет выполнение вашего кода, но со временем может исчезнуть.
Тупиковая ситуация возникает, когда поток ожидает ресурса, заблокированного вторым потоком, а второй поток ожидает ресурса, заблокированного первым потоком. В тупик может попасть более двух потоков. Тупиковая ситуация никогда не разрешается сама собой. Это часто приводит к остановке всего приложения или той части, которая находится в тупике.
Я думаю, что должны быть некоторые разъяснения от OP на фоне вопроса - я могу придумать 2 ответа (хотя я уверен, что в этот список есть дополнения):
если вы имеете в виду общую «концепцию» конкуренции потоков и то, как она может проявляться в приложении, я полагаюсь на подробный ответ @ DavidSchwartz выше.
Существует также счетчик производительности .NET CLR Locks and Threads: Total # of Contentions. Согласно описанию PerfMon для этого счетчика, он определяется как:
Этот счетчик отображает общее количество раз, когда потоки в CLR безуспешно пытались получить управляемую блокировку. Управляемые блокировки можно получить разными способами; с помощью оператора «lock» в C # или путем вызова System.Monitor.Enter или с помощью настраиваемого атрибута MethodImplOptions.Synchronized.
... и я уверен, что другие для других ОС и приложений.
Другое слово может быть параллелизм. Это просто идея двух или более потоков, пытающихся использовать один и тот же ресурс.
Представьте себе следующий сценарий. Вы готовитесь к завтрашнему заключительному экзамену и немного проголодались. Итак, вы даете своему младшему брату десять баксов и просите его купить вам пиццу. В этом случае вы являетесь основным потоком, а ваш брат - дочерним потоком. После того, как ваш заказ сделан, вы и ваш брат одновременно выполняете свою работу (т. Е. Учитесь и покупаете пиццу). Теперь нам нужно рассмотреть два случая. Сначала ваш брат приносит вашу пиццу и прекращает занятия, пока вы учитесь. В этом случае можно бросить учебу и насладиться пиццей. Во-вторых, вы рано заканчиваете учебу и ложитесь спать (то есть, ваша назначенная работа на сегодня - подготовка к завтрашнему выпускному экзамену - выполнена) до того, как пицца будет доступна. Конечно, вы не можете заснуть; иначе у вас не будет возможности съесть пиццу.
Как и в примере, эти два случая означают соперничество.
Конфликт блокировок имеет место, когда поток пытается получить блокировку для объекта, который уже был получен другим потоком *. Пока объект не будет освобожден, поток блокируется (другими словами, он находится в состоянии ожидания). В некоторых случаях это может привести к так называемому последовательному выполнению, что отрицательно скажется на приложении.