Я настоятельно рекомендую вам посмотреть эти видео. Затем просмотрите примеры, которые я предоставил, а затем измените код и поиграйте с ними столько, сколько сможете. Мне потребовалось 3 года, чтобы полностью освоиться с многопоточностью iOS, поэтому не торопитесь: D
Посмотрите первые 3 минуты этого видео RWDevCon и более, если хотите.
Также смотрите 3: 45 до 6: 15 . Хотя я рекомендую вам посмотреть это видео полностью.
Подводя итог тем моментам, о которых говорилось в видео, за упомянутую мною продолжительность:
многопоточность и параллелизм относятся к очереди source и destination . очередь.
синхронизация и асинхронность, в частности, зависит от очереди источника.
Подумайте об исходных и конечных очередях шоссе, где ваша работа выполняется.
Если вы выполните async , то вы как бы отправляете машину (должна доставить вещи), выезжая с шоссе, а затем продолжаете позволять другим машинам двигаться по шоссе.
Если вы выполните sync , то вы как бы отправляете машину (должна доставить вещи) с шоссе и затем прекращаете позволять любой машине продолжать, пока машина не доставит все свои вещи.
Думайте об автомобиле, который доставляет вещи как блок кода, начиная и заканчивая выполнением.
То, что происходит для основной очереди, идентично тому, что происходит для последовательной очереди. Они обе последовательные очереди.
Так что, если вы уже находитесь в главном потоке и отправляете в основной поток, а затем отправляете асинхронно, все, что вы отправите, будет отправлено в конец очереди
Чтобы показатьВы, что я имею в виду: в каком порядке, как вы думаете, это будет печатать? Вы можете легко проверить это на игровой площадке:
DispatchQueue.main.async {
print("1")
print("2")
print("3")
DispatchQueue.main.async {
DispatchQueue.main.async {
print("4")
}
print("5")
print("6")
print("7")
}
print("8")
}
DispatchQueue.main.async {
print("9")
print("10")
}
Будет напечатано:
1
2
3
8
9
10
5
6
7
4
Почему?
Это происходит главным образом потому, что каждый раз, когда вы отправляете на главную, это будетперейти в конец очереди.
Отправка на главную, когда вы уже в главной очереди, является очень скрытой скрытой причиной многих крошечных задержек , которые вы видите в пользовательском взаимодействии приложения.
Что произойдет, если вы отправите в ту же очередь serial , используя sync ?
Deadlock! См. здесь
Если вы отправляете в одну и ту же очередь одновременного , используя sync , то у вас не будет тупика. Но любой другой поток будет просто ждать, пока вы выполните sync . Я обсуждал это ниже.
Теперь, если вы пытаетесь отправить в параллельную очередь, тогда, если вы делаете sync , это похоже на пример шоссе,где вся 5-полосная магистраль заблокирована, пока машина не доставит все. Но синхронизировать в параллельной очереди довольно бесполезно, если только вы не делаете что-то вроде .barrier
очереди и не пытаетесь решить проблему read-write .
Но чтобы увидеть, что произойдет, если вы выполните синхронизацию в параллельной очереди:
let queue = DispatchQueue(label: "aConcurrentQueue", attributes: .concurrent)
for i in 0...4 {
if i == 3 {
queue.sync {
someOperation(iteration: UInt32(i))
}
} else {
queue.async {
someOperation(iteration: UInt32(i))
}
}
}
func someOperation(iteration: UInt32) {
sleep(1)
print("iteration", iteration)
}
запишет:
// '3' will ALWAYS be first, because it's chocking the entire queue.
// The rest happen concurrently. And each time you run the app, the sequence of the rest would be different, because of the nature of concurrency. But likely 4 will be closer to being completed last and 0 would be closer to being finished sooner.
iteration 3
iteration 0
iteration 2
iteration 1
iteration 4
Если вы выполните async напараллельная очередь, тогда предположим, что у вас есть ограниченное количество одновременных потоков, например, 5, то 5 задач будут выполняться одновременно. Просто каждая заданная задача идет в конец очереди. Было бы целесообразно сделать это для ведения журнала. Вы можете иметь несколько тем журнала. Один поток регистрирует события местоположения, другой регистрирует покупки и т. Д.
Хорошим примером игровой площадки будет:
let queue = DispatchQueue(label: "serial", attributes: .concurrent)
func delay(seconds: UInt32 ) {
queue.async {
sleep(seconds)
print(seconds)
}
}
for i in (1...5).reversed() {
delay(seconds: UInt32(i))
}
Даже если вы сначала отправили 5, это вывело бы
1
2
3
4
5