Відповіді:
По суті вміст потоку - це умова, коли одна нитка чекає на замок / об'єкт, який зараз утримується іншим потоком. Отже, цей потік очікування не може використовувати цей об’єкт, поки інший потік не розблокує цей конкретний об'єкт.
Здається, кілька відповідей зосереджуються на суперечливості блокування, але блокування - це не єдиний ресурс, щодо якого можна переживати суперечку. Суперечка - це просто тоді, коли два потоки намагаються отримати доступ до одного і того ж ресурсу або пов'язаних з ним ресурсів таким чином, що принаймні один з конкуруючих потоків працює повільніше, ніж це було б, якби інші потоки не працювали.
Найбільш очевидний приклад сварки - це замок. Якщо в потоці A є замок, а потік B хоче придбати той самий замок, нитці B доведеться почекати, поки нитка A звільнить замок.
Тепер це стосується платформи, але потік може зазнати уповільнення, навіть якщо йому ніколи не доведеться чекати, коли інший потік звільнить замок! Це відбувається тому, що блокування захищає певні дані, і самі дані часто також будуть оскаржуватися.
Наприклад, розглянемо потік, який набуває замок, модифікує об’єкт, потім звільняє замок і виконує деякі інші речі. Якщо два потоки роблять це, навіть якщо вони ніколи не борються за блокування, вони можуть працювати набагато повільніше, ніж це було б, якби працювала лише одна нитка.
Чому? Скажімо, кожен потік працює на власному ядрі на сучасному процесорі x86, а ядра не поділяють кеш L2. За допомогою лише одного потоку об'єкт може залишатися в кеші L2 більшу частину часу. Коли обидва потоки запущені, кожен раз, коли один потік модифікує об'єкт, інший потік виявить, що дані не є в його кеші L2, оскільки інший процесор визнав недійсним рядок кешу. Наприклад, на Pentium D це призведе до запуску коду зі швидкістю FSB, що набагато менше швидкості кешу L2.
Оскільки суперечки можуть виникати, навіть якщо замок не претендує на себе, сварка може виникати і тоді, коли блокування немає. Наприклад, скажімо, ваш процесор підтримує атомний приріст 32-бітної змінної. Якщо один потік продовжує збільшувати і зменшувати змінну, велика частина часу змінна буде гарячою в кеші. Якщо це зробити два потоки, їх кеші будуть претендувати на право власності на пам'ять, що містить цю змінну, і багато доступу будуть повільнішими, оскільки протокол когерентності кеш-пам'яті працює для захисту кожного основного права власності на кеш-лінію.
За іронією долі, замки зазвичай зменшують суперечки. Чому? Оскільки без блокування два потоки можуть працювати на одному об’єкті або колекції і викликати багато суперечок (наприклад, існують черги без блокування). Блоки, як правило, відкладають суперечливі потоки, дозволяючи замість цього запускати непереборні потоки. Якщо потік A містить замок, а потік B хоче цього самого блокування, реалізація може замість цього виконати потік C. Якщо потоку C не потрібен цей замок, тоді можна буде уникнути майбутньої суперечки між потоками A і B на деякий час. (Звичайно, це передбачає, що можуть бути запущені інші потоки. Це не допоможе, якщо єдиний спосіб, коли система в цілому може досягти корисного прогресу, - це запуск ниток, які суперечать.)
Від сюди :
Суперечка виникає, коли нитка чекає ресурсу, який недоступний; це уповільнює виконання коду, але з часом може очиститися.
Тупик виникає, коли нитка чекає ресурсу, який другий потік заблокував, а другий потік очікує ресурс, який заблокував перший потік. Більше двох потоків можуть бути задіяні в тупику. Тупик ніколи не вирішує себе. Це часто спричиняє зупинку всієї програми або тієї частини, яка переживає тупик.
Я думаю, що на тлі питання має бути якесь уточнення з ОП - я можу придумати 2 відповіді (хоча я впевнений, що до цього списку є доповнення):
якщо ви маєте на увазі загальну "концепцію" вмісту ниток і як вона може представити себе в додатку, я відкладаю детальну відповідь @ DavidSchwartz вище.
Існує також ". NTP CLR Locks and Threads: Total # of Contentions" Лічильник ефективності. Як взято з опису PerfMon для цього лічильника, він визначається як:
Цей лічильник відображає загальну кількість разів, коли потоки в CLR невдало намагаються придбати керований замок. Керовані замки можна придбати різними способами; за допомогою оператора "lock" в C # або за допомогою виклику System.Monitor.Enter або за допомогою користувальницького атрибута MethodImplOptions.Synchronized.
... і я впевнений, що інші стосуються інших ОС і програм.
Іншим словом може бути паралельність. Це просто ідея двох або більше потоків, які намагаються використовувати один і той же ресурс.
Уявіть такий сценарій. Ви готуєтесь до завтрашнього випускного іспиту і відчуваєте трохи голоду. Отже, ви даєте своєму молодшому братові десять баксів і просите його придбати для вас піцу. У цьому випадку ви є основною ниткою, а ваш брат - дочірньою ниткою. Після того, як ваше замовлення надано, ви і ваш брат одночасно виконуєте свою роботу (тобто вивчаєте та купуєте піцу). Зараз ми маємо розглянути два випадки. По-перше, ваш брат повертає вашу піцу назад і припиняє, поки ви навчаєтесь. У цьому випадку ви можете припинити навчання та насолоджуватися піцею. По-друге, ви закінчуєте навчання рано і спите (тобто ваша призначена робота на сьогодні - навчання на завтрашній випускний іспит - буде виконано), перш ніж піца буде доступна. Звичайно, ти не можеш спати; інакше у вас не буде можливості з'їсти піцу.
Як і в прикладі, два випадки дають значення суперництву.
Суперечка щодо блокування відбувається, коли потік намагається придбати замок для об'єкта, який вже набутий іншим потоком *. Поки об’єкт не звільнений, потік блокується (іншими словами, він знаходиться в стані очікування). У деяких випадках це може призвести до так званого серійного виконання, що негативно позначається на застосуванні.