Ні, до тих пір, поки ви не замикаєтесь на одному об’єкті. Рекурсивний код фактично вже має блокування і тому може безперешкодно тривати.
lock(object) {...}
це скорочення для використання класу Monitor . Як вказує Марк , Monitor
допускається повторне введення в дію , тому неодноразові спроби блокування об'єкта, на якому в поточній нитці вже є замок, будуть працювати добре.
Якщо ви почнете фіксувати різні об’єкти, тоді потрібно бути обережним. Зверніть особливу увагу на:
- Завжди купуйте замки на заданій кількості об'єктів в одній послідовності.
- Завжди відпускайте замки у зворотному порядку, як ви їх придбали.
Якщо ви порушите будь-яке з цих правил, ви майже гарантовано отримаєте проблеми з тупиком в якийсь момент .
Ось одна гарна веб-сторінка, що описує синхронізацію потоків у .NET: http://dotnetdebug.net/2005/07/20/monitor-class-avoiding-deadlocks/
Також заблокуйте якомога менше об’єктів одночасно. Розгляньте можливість застосування грубозернистих замків, де це можливо. Ідея полягає в тому, що якщо ви можете написати свій код таким, що є об’єктний графік, і ви можете придбати замки в корені цього об'єктного графіка, тоді зробіть це. Це означає, що у вас є один замок на цьому кореневому об’єкті, і тому не потрібно так сильно хвилюватися щодо послідовності придбання / звільнення блокування.
(Ще одне зауваження, ваш приклад не є технічно рекурсивним. Щоб він був рекурсивним, Bar()
потрібно було б називати себе, як правило, частиною ітерації.)