#multithreading #asynchronous #async-await #locking #deadlock
Вопрос:
Недавно я был на собеседовании, и это был вопрос, по которому мне было отказано, так что было бы очень приятно узнать, как решить эту проблему в будущем.
Сначала они спросили меня, как решить простую тупиковую проблему, такую как
lock(a) { lock(b) { // do smth } } lock(b) { lock(a) { // do smth } }
После того, как я сказал: просто исправьте порядок блокировки, который они просили в следующий раз:
Вот идет какой-то псевдокод (потому что он не имеет отношения к языку и потому что я не помню, что именно там было).
function void foo(T[] arr) { lock(arr[randint(arr.length)]) { lock(arr[randint(arr.length)]) { // do smth } } } var arr = new arr{...} async () =gt; { foo(arr) foo(arr) }
Вопрос в следующем: Как решить эту проблему автоматически UPD: это было интервью на C#, так что, возможно, только на этом языке есть инструменты для решения этой проблемы (я так не думаю, но это следует отметить, чтобы не вызвать недоразумений).
Комментарии:
1. К вашему сведению: Эта головоломка иллюстрирует, как возникают тупики в реальных программах. В другом варианте блокировки передаются функции в виде двух аргументов. Подсказка: Решение для версии массива немного более очевидно, потому что каждая из блокировок имеет свой собственный уникальный индекс в массиве.
Ответ №1:
Итак, я некоторое время искал и расспрашивал людей, но никто ничего не сказал, кроме «Используйте потокобезопасные коллекции».
Комментарии:
1. Я не видел вашего вопроса до сих пор, но, как утверждает Соломон в комментариях, обрабатывать массивы легко. Зафиксируйте индексы в порядке возрастания. Потокобезопасные коллекции здесь не являются ответом, потому что потокобезопасные коллекции не решают заданный вами вопрос. Массивы совершенно безопасны для доступа к перекрестным потокам, но если вам нужно ввести блокировки вокруг элементов, потокобезопасные коллекции вам не помогут.