GCD - Grand Central Dispatch


#1

Ребят всем привет!

Сейчас изучаю курс Ивана по GCD, и так сложилось что не дойдя до данной темы меня позвали на собеседование, где предоставили простую задачу на данную тему.

Собственно хотел задать несколько вопросов по GCD.

Вопрос 1. В чем смысл добавления задач в Serial Queue асинхронно (async)

let queue = DispatchQueue(label: "Serial Queue)

queue.async {
    print("Block 1")
}

P.S.Если я все правильно понял, задачи помещенные в Serial Queue, выполняются в строгой последовательности (FIFO, т.е. пока не завершится текущая задача в очереди, не начнется задача которая стоит следующей в очереди. Sync позволяет помещать задачи в очередь синхронно, т.е. мы дожидаемся ее выполнения. Async позволяет помещать задачи в очередь асинхронно, что подразумевает что мы не дожидается завершения выполнения задач, помещенных с помощью async.

Тогда какой смысл использовать для последовательной очереди async? Если можно сделать все через sync

Вопрос 2. Есть ли разница между следующими листингами

queue.async {
  print("Block 1")
    queue.async {
      print("Block 2")
 }
}

и

queue.async {
  print("Block 1")
}

 queue.async {
  print("Block 2")
}

P.S.Меняется ли логика выполнения кода от вложенности ?

Вопрос 3. Пример с вопроса на собеседовании, с которым я не справился. Нужно объяснить что будет происходить в случае листинга указанного под номером 1 и листинга указанным под номером 2.

1)let queue = DispatchQueue(label: "com.app.queue")

queue.async { ... }

queue.async {
    print("Task 1")

 queue.sync {
    print("Task 2")
 }

  print("Task 3")
 }

2)let queue = DispatchQueue(label: "com.app.queue")

queue.async { ... }

queue.async {
  print("Task 1")

  queue.async {
    print("Task 2")
  }

  print("Task 3")
}

P.S.Здесь я смог норм выдать только то что мы создаем в обоих случаях последовательную очередь в которую помещаем задачи. Сразу начал путаться из за вложенности в очередях. Можете пожалуйста помочь разобраться в очередности выполнения задач - как и что происходит в данном случае, на этой теме завис сильно, не могу прочувствовать логику работы при помещении в очередь задач синхронно/асинхронно


#2

Сам сегодня весь день освежал многопоточность и очереди. Вопрос на засыпку разницу понимаешь? :slight_smile:
Более опытные товарищи меня поправят (я могу тут опечатки сделать или глупость сморозить).

Короче, с последовательной очередью пришло понимание.
Если выполнять код синхронно, то понятно, главный поток подвиснет на момент выполнения.

Если выполнять асинхронно, то в твоем случае будет блок 1 и все. Ты эффекта не заметишь.
Нужно выполнить что-то типа:

let queue = DispatchQueue(label: "serial queue")

queue.async {
	for i in 1...10_000_000 {
		if i == 10_000_000 {
			print("block 1")
		}
	}
	print("block 2")
}
queue.async {
	for i in 1...100000 {
		if i == 100000 {
			print("block 3")
		}
	}
	print("block 4")
}

print("end")

Там фишка в чем. Создается очередь (любую картинку загугли). И очередь выполнять задачи будет последовательно. Если вызывать код асинхронно, то они выполняться будут в отдельных потоках, но все равно последовательно. В примере что кидал, блоки будут выводится не по мере выполнения (кто быстрей тот и вывелся), а с 1 по 4й.


#3

По второму вопросу, мне кажется, разницы нет. Лень проверять.
Но у тебя асинхронно выполниться что в первом случае блок 1 и блок 2. Что во втором. Всегда будет последовательно выводится.


#4

По 3 вопросу.

Ну тут в 1 случае выведется:
Task 3
Task 1
Task 2

Во 2 случае:

Task 1
Task 3
Task 2

Но это я из головы написал. Позжей проверю в плейграунде.


#5

в первом случае падает здесь

queue.sync {
print(“Task 2”)
}

#6

Форматируйте код перед публикацией!


#7

А, sync не заметил. Да, правильно, тут заметили. Форматируйте код.


#8

Оно не падает, а зависает. Это вроде как deadlock хапнули.

С потоками мнонго приколов:

  • Условия гонки
  • Конкуренция за ресурс
  • Вечная блокировка (deadlock)
  • livelock - противоположность deadlock-у. не знаю как перевести.
  • Голодание
  • Инверсия приоритетов
  • Неопределенность и справедливость

#9

верно!
Если очередь сделать .concurrent, то deadlock уже не будет иметь место.