@sportredwhite

Deadlcok в swift?

Ребят никак не могу понять daedlock, race condition понял, а вот deadlock никак(
Объясните плз

Почему когда вызываю DispatchQueue.main.sync {} в main потоке, идёт взаимная блокировка?
Я понимаю, что sync блокирует поток. Но ведь когда задача выполнится, main поток опять свободен.
И почему задача в DispatchQueue.main.sync {} не может быть выполнена?

И ещё тут же спрошу, другую задачу)

print("a")
DispatchQueue.main.async {
    DispatchQueue.main.async {
        print("b")
    }
    print("c")
}
print("d")


Почему ответ будет a, d, c, b ?

Потому что DispatchQueue.main.async {} уходит в конец очереди? что именно здесь происходит?
  • Вопрос задан
  • 4984 просмотра
Решения вопроса 1
doublench21
@doublench21 Куратор тега Swift
Это справедливо не только для главного потока, НО и для всех последовательных очередей.

Рассмотрим вот такой пример:
5c76b22e12b96350728646.png

Что мы получаем:
Очевидно, всякая последовательная очередь ждёт выполнения текущей задачи, перед тем как начать выполнять следующую. Когда мы пытаемся СИНХРОННО поставить в очередь текущую задачу, мы получаем блокировку. Это происходит потому, что когда мы выполняем код (3-я строчка), то мы это делаем в рамках текущей, уже выполняющейся в очереди задачи И пытаемся синхронно добавить задачу. Синхронно означает, что мы должны дождаться завершения текущей задачи. Но как мы можем завершить задачу в которой мы находимся, если мы сами её и тормозим? Это и называется взаимной блокировкой. 2-ая строка кода ждёт выполнения 3-ей строки, а 3-я строка ждёт завершения 2-ой. Под строками я понимаю собственно блоки кода, которые мы добавляем в ПОСЛЕДОВАТЕЛЬНУЮ очередь.

А что до главного потока, это происходит неявно. Ведь мы по умолчанию уже находимся внутри задачи помещенной в главную очередь. И если мы попытаемся сделать так же, как и в 3-ей строке - получим блокировку.

Об этом написано у Apple:
Do not call the dispatch_sync function from a task that is executing on the same queue that you pass to your function call. Doing so will deadlock the queue. If you need to dispatch to the current queue, do so asynchronously using the dispatch_async function.


Касаемо:
5c76b5872101c484838312.png
Будем идти по порядку. Начинаем с #1 - печатаем "a". После выполняем #2. Тут мы АСИНХРОННО добавляем в очередь задачу. Это значит, что мы говорим системе, эй, поставь эту задачу в очередь и верни мне контроль над кодом, я не хочу ждать. Поэтому после #2 тут же выполняется #6. Ведь мы и сказали, что не хотим ждать завершения добавленной задачи. Вот он и вернул управления и продолжил выполнять. То есть вывел символ "d".
Теперь внутри очереди мы снова добавляем АСИНХРОННО новую задачу в рамках текущей задачи. То есть мы так же говорим, что бы система передала управление обратно и мы не хотим ждать завершения. То есть после добавления задачи мы тут же выполняем строку #5 - выводим символ "c".

Так как добавить задачу в очередь занимает некоторое время, плюс то время, что тратится на выполнение самой задачи - всё это приводит к тому, что вывод строки #4 пришелся самым последним.

То есть всё это время мы просили лишь добавить задачи в очередь и продолжить выполнять следующие строчки кода не дожидаясь их завершения. Вот символы "a, d, c" и вывелись раньше символа "b".

Не знаю как ещё проще объяснить. Может кто поправит меня.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы