Що таке суперечка з нитками?


120

Чи може хтось, будь ласка, пояснити просто, що таке суперечка ниток?

Я переглянув це, але не можу знайти просте пояснення.


9
Тож напишіть, яка у вас неясна думка, і ми зможемо побачити, де ви можете відключитися, або ваше розуміння може бути правильним.
Джеймс Блек

Відповіді:


87

По суті вміст потоку - це умова, коли одна нитка чекає на замок / об'єкт, який зараз утримується іншим потоком. Отже, цей потік очікування не може використовувати цей об’єкт, поки інший потік не розблокує цей конкретний об'єкт.


53
Ця відповідь є неповною (як і більшість інших). Незважаючи на те, що замок - це один із видів речей, щодо якого може бути суперечка, він далеко не єдиний. Тут можуть бути суперечки і за безцінні ресурси. (Наприклад, якщо два потоки атомно збільшуються в одному цілому цілому, у них може виникнути суперечки через кешинг ping-ponging. Жодних замків не задіяно.)
David Schwartz

У випадку з глобальним блоком інтерпретаторів (GIL), таким як у CPython, де потік завжди повинен отримувати GIL, тому декілька потоків, що працюють в одному і тому ж процесі, за замовчуванням суперечать.
Acumenus

Я думаю, ви пояснили це з точки зору тупика, але він дуже сильно відрізняється від тупикового.
Харшит Гупта

185

Здається, кілька відповідей зосереджуються на суперечливості блокування, але блокування - це не єдиний ресурс, щодо якого можна переживати суперечку. Суперечка - це просто тоді, коли два потоки намагаються отримати доступ до одного і того ж ресурсу або пов'язаних з ним ресурсів таким чином, що принаймні один з конкуруючих потоків працює повільніше, ніж це було б, якби інші потоки не працювали.

Найбільш очевидний приклад сварки - це замок. Якщо в потоці A є замок, а потік B хоче придбати той самий замок, нитці B доведеться почекати, поки нитка A звільнить замок.

Тепер це стосується платформи, але потік може зазнати уповільнення, навіть якщо йому ніколи не доведеться чекати, коли інший потік звільнить замок! Це відбувається тому, що блокування захищає певні дані, і самі дані часто також будуть оскаржуватися.

Наприклад, розглянемо потік, який набуває замок, модифікує об’єкт, потім звільняє замок і виконує деякі інші речі. Якщо два потоки роблять це, навіть якщо вони ніколи не борються за блокування, вони можуть працювати набагато повільніше, ніж це було б, якби працювала лише одна нитка.

Чому? Скажімо, кожен потік працює на власному ядрі на сучасному процесорі x86, а ядра не поділяють кеш L2. За допомогою лише одного потоку об'єкт може залишатися в кеші L2 більшу частину часу. Коли обидва потоки запущені, кожен раз, коли один потік модифікує об'єкт, інший потік виявить, що дані не є в його кеші L2, оскільки інший процесор визнав недійсним рядок кешу. Наприклад, на Pentium D це призведе до запуску коду зі швидкістю FSB, що набагато менше швидкості кешу L2.

Оскільки суперечки можуть виникати, навіть якщо замок не претендує на себе, сварка може виникати і тоді, коли блокування немає. Наприклад, скажімо, ваш процесор підтримує атомний приріст 32-бітної змінної. Якщо один потік продовжує збільшувати і зменшувати змінну, велика частина часу змінна буде гарячою в кеші. Якщо це зробити два потоки, їх кеші будуть претендувати на право власності на пам'ять, що містить цю змінну, і багато доступу будуть повільнішими, оскільки протокол когерентності кеш-пам'яті працює для захисту кожного основного права власності на кеш-лінію.

За іронією долі, замки зазвичай зменшують суперечки. Чому? Оскільки без блокування два потоки можуть працювати на одному об’єкті або колекції і викликати багато суперечок (наприклад, існують черги без блокування). Блоки, як правило, відкладають суперечливі потоки, дозволяючи замість цього запускати непереборні потоки. Якщо потік A містить замок, а потік B хоче цього самого блокування, реалізація може замість цього виконати потік C. Якщо потоку C не потрібен цей замок, тоді можна буде уникнути майбутньої суперечки між потоками A і B на деякий час. (Звичайно, це передбачає, що можуть бути запущені інші потоки. Це не допоможе, якщо єдиний спосіб, коли система в цілому може досягти корисного прогресу, - це запуск ниток, які суперечать.)


4
+1 Крім того, щоб зробити це явним, дві змінні, над якими билися два ядра, навіть не повинні бути однаковою змінною, щоб викликати суперечки, вони повинні зберігатися в пам'яті лише в тому ж рядку кешу. Складні конструкції та / або вирівнювання конструкцій пам’яті можуть допомогти уникнути цієї форми суперечок.
Rob_before_edits

1
@David, будь ласка, допоможіть більш детально зрозуміти останній пункт вашої відповіді
Учень

4
@Naroji Задайте питання про це.
Девід Шварц

@DavidSchwartz, ти програміст C?
Pacerier

В основному @Pacerier C ++.
Девід Шварц

19

Від сюди :

Суперечка виникає, коли нитка чекає ресурсу, який недоступний; це уповільнює виконання коду, але з часом може очиститися.

Тупик виникає, коли нитка чекає ресурсу, який другий потік заблокував, а другий потік очікує ресурс, який заблокував перший потік. Більше двох потоків можуть бути задіяні в тупику. Тупик ніколи не вирішує себе. Це часто спричиняє зупинку всієї програми або тієї частини, яка переживає тупик.


Це також пояснює різницю між
контентом «Thunder»

3

Я думаю, що на тлі питання має бути якесь уточнення з ОП - я можу придумати 2 відповіді (хоча я впевнений, що до цього списку є доповнення):

  1. якщо ви маєте на увазі загальну "концепцію" вмісту ниток і як вона може представити себе в додатку, я відкладаю детальну відповідь @ DavidSchwartz вище.

  2. Існує також ". NTP CLR Locks and Threads: Total # of Contentions" Лічильник ефективності. Як взято з опису PerfMon для цього лічильника, він визначається як:

    Цей лічильник відображає загальну кількість разів, коли потоки в CLR невдало намагаються придбати керований замок. Керовані замки можна придбати різними способами; за допомогою оператора "lock" в C # або за допомогою виклику System.Monitor.Enter або за допомогою користувальницького атрибута MethodImplOptions.Synchronized.

... і я впевнений, що інші стосуються інших ОС і програм.


2

У вас є 2 нитки. Нитка A і Нитка B, у вас також є об'єкт C.

В даний час A отримує доступ до об'єкта C і розмістив замок на цьому об'єкті. B потрібно отримати доступ до об'єкта C, але не може цього зробити, поки A не відпустить блокування об'єкта C.


1

Іншим словом може бути паралельність. Це просто ідея двох або більше потоків, які намагаються використовувати один і той же ресурс.


1

Для мене суперечка - це конкуренція між 2 або більше потоками за спільний ресурс. Ресурс може бути замком, лічильником тощо. Конкурс означає "хто отримує його першим". Чим більше ниток, тим більше суперечок. Чим частіший доступ до ресурсу, тим більше суперечок.


1

Уявіть такий сценарій. Ви готуєтесь до завтрашнього випускного іспиту і відчуваєте трохи голоду. Отже, ви даєте своєму молодшому братові десять баксів і просите його придбати для вас піцу. У цьому випадку ви є основною ниткою, а ваш брат - дочірньою ниткою. Після того, як ваше замовлення надано, ви і ваш брат одночасно виконуєте свою роботу (тобто вивчаєте та купуєте піцу). Зараз ми маємо розглянути два випадки. По-перше, ваш брат повертає вашу піцу назад і припиняє, поки ви навчаєтесь. У цьому випадку ви можете припинити навчання та насолоджуватися піцею. По-друге, ви закінчуєте навчання рано і спите (тобто ваша призначена робота на сьогодні - навчання на завтрашній випускний іспит - буде виконано), перш ніж піца буде доступна. Звичайно, ти не можеш спати; інакше у вас не буде можливості з'їсти піцу.

Як і в прикладі, два випадки дають значення суперництву.


0

На суперечність ниток також впливають операції вводу / виводу. Приклад, коли нитка, що чекає на файл, прочитана, вона може розглядатися як суперечка. Використовуйте порти для завершення вводу / виводу як рішення.


0

Суперечка щодо блокування відбувається, коли потік намагається придбати замок для об'єкта, який вже набутий іншим потоком *. Поки об’єкт не звільнений, потік блокується (іншими словами, він знаходиться в стані очікування). У деяких випадках це може призвести до так званого серійного виконання, що негативно позначається на застосуванні.

з документації dotTrace

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.