Неправдиве пояснення пробудження звучить як помилка, яку просто не варто виправляти, правда?


30

Згідно зі статтею Вікіпедії про Грізні пробудження

"поток може бути пробуджений із стану очікування, навіть якщо жодна нитка не сигналізує про змінну умову".

Хоча я знаю про цю "особливість", я ніколи не знав, що насправді викликало її, до тієї ж статті

"Помилкові пробудження можуть здаватися дивними, але в деяких багатопроцесорних системах зробити так, що пробудження стану повністю передбачуване може істотно сповільнити всі операції зі змінною умовою."

Звучить помилка, яку просто не варто виправляти, правда?


1
пов'язаний: «Чому pthread_cond_wait має паразитне пробудження?», stackoverflow.com/questions/8594591 / ...
Флоріан CASTELLANE

Відповіді:


39

TL; DR Припущення ("контракт") помилкових пробуджень - це розумне архітектурне рішення, прийняте для забезпечення реально надійних реалізацій планувальників ниток.

"Міркування щодо ефективності" тут не мають значення, це лише непорозуміння, які набули поширення через те, що вони заявили в опублікованій авторитетній довідці. (авторитетні посилання можуть мати помилки, знаєте - просто запитайте Галілео Галілея ) Стаття Вікіпедії зберігає посилання на замітку, яку ви цитували, лише тому, що вона повністю відповідає їх формальним рекомендаціям цитування опублікованої посилання.

Набагато переконливіша причина введення концепції хибних пробуджень надана у цій відповіді на ПЗ, яка ґрунтується на додаткових подробицях, наведених у (старішій версії) цієї самої статті:

Стаття Вікіпедії про помилкові пробудження має такий примх :

pthread_cond_wait()Функція в Linux здійснюється з допомогою futexсистемного виклику. Кожен системний виклик блокування в Linux різко повертається, EINTRколи процес отримує сигнал. ... pthread_cond_wait()не може перезапустити очікування, оскільки це може пропустити справжнє пробудження в той час, коли він був поза futexсистемним дзвінком ...

Подумайте про це ... як і будь-який код, у планувальник потоків може виникнути тимчасове затемнення через щось ненормальне, що відбувається в базовому апаратному / програмному забезпеченні. Звичайно, слід подбати про те, щоб це сталося якомога рідше, але оскільки не існує такого поняття, як 100% надійне програмне забезпечення, розумно припустити, що це може статися, і подбати про витончене відновлення у випадку, якщо планувальник виявить це (наприклад, спостерігаючи за відсутніми серцебиттями ).

Тепер, як планувальник може відновитись, враховуючи, що під час затемнення він може пропускати деякі сигнали, призначені для сповіщення потоків очікування? Якщо планувальник нічого не робить, згадані "нещасливі" потоки просто зависять, чекаючи вічно - щоб уникнути цього, планувальник просто надішле сигнал усім потокам, що очікують.

Це обумовлює необхідність встановлення "контракту" про те, що нитка очікування може бути повідомлена без причини. Якщо бути точним, є причина - затемнення планувальника, але оскільки нитка розроблена (з поважної причини), щоб не забувати про деталі внутрішньої реалізації планувальника, ця причина, швидше за все, краще представити як "хибну".


З точки зору нитки, це дещо нагадує закон Постеля (він же принцип надійності ),

будьте консервативними у тому, що робите, будьте ліберальні у тому, що приймаєте від інших

Припущення помилкових пробуджень змушує нитку бути консервативним у тому, що вона робить : встановити умову при повідомленні інших потоків і ліберальну в тому, що вона приймає : перевірити умову при будь-якому поверненні з очікування і повторити очікування, якщо її ще немає.


10
Тьфу ... Закон Постеля ... причина, чому HTML і всілякі веб-технології так багато лайно кидають у них (наприклад, прийняття HTML-коду поганих тегів). Це вбік, хороша відповідь.
Томас Едінг

3
Закон Postel - це те, чому багато помилок роками залишаються невловимими, бо ей, навіть якщо ваша функція повертає неправильний вихід, додаток все одно працює! Найкращий винахід коли-небудь.
Pacerier

2
@Pacerier: функція, що повертає неправильний вихід, не відповідає закону Postel (консервативна частина).
YvesgereY

@Pacerier: OTOH, вимагаючи, щоб інші компоненти були суворі, щоб помилки могли бути зловлені раніше, є цікавою позицією, помиляючись на стороні принципу "Fail Fast" та "Контрактного дизайну".
YvesgereY

1

Фіксувати його не варто, оскільки код абонента повинен використовувати той самий режим (перевірку стану), щоб вирішити стан перегонів.

Одне звернення до двох питань, яке я підсумовую таким:

Неправдиве пробудження: очікування потоку планується до встановлення умови.
Примусове проспання: очікування потоку планується після того, як умова знову буде фальсифікована.

Оскільки пізніше це може статися, деякі пішли аж до введення помилкового пробудження в контракт:

  • застосовувати передовий досвід, вимагаючи циклів предикатів.
  • дати деяку свободу для впровадження планувальника (включаючи можливість відновлення у надзвичайних ситуаціях, як вказував @gnat).

ТАК посилання


Я хотів би поставити +1 цьому, але для ідеї, що хтось навмисно запровадив помилкові пробудження, щоб змусити абонентів додати петлі предиката для адреси вимушених проспань. Я вважаю це немислимим.
ruakh

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