Я более менее разобрался с понятиями очередей, потоков и их видов, но на практике очень сложно сопоставить с реальными задачами. Я понял что отностельно главного потока я могу создать параллельный поток с sync или asyc очередью, но есть одно но. С concurrent потоками я разобрался как работать относительно main thread, а вот как работать с serial относиттельно главного потока или любого другого потока и как о себя ведёт при asyn и sync непонятно. Кто может объясните пожалуйста про serialQueue) Буду очень благодарен. Было бы круто если покажете на рисунке. Для парллельного потока это выглядит как две параллельные линии а для serial как
Здравствуйте, уже неделю не могу понять некоторых ньюансов в теме многопоточности
Относительно любой очереди, любая другая (или та же самая) очередь, или блокирует её (sync) или не блокирует (async).
В последовательной очереди всего один поток, когда вы выполняете код асинхронно, что бы очередь не блокировалась ваш код перемещаться в её конец, то есть асинхронный код выполниться когда очередь освободиться:
DispatchQueue.main.async {
print("0")
}
print("1")
print("2")
print("3")
// Output: 1, 2, 3, 0 // Всегда в таком порядке
В параллельной очереди несколько потоков, асинхронный код выполняется в отдельном потоке, то есть сразу и никого не ждёт:
let queue = DispatchQueue.global(qos: .default)
queue.sync {
queue.async {
print("0")
}
print("1")
print("2")
print("3")
}
// Output: 1, 0, 2, 3 // Может быть любой другой порядок
А можете тоже самое и про синхронное рассказать(прям те же примеры но с синхронной очередью)? просто мне не понятно зачем использовать параллельную синхронную очередь ведь в ней задачи будут выполнятся также как и параллельной очереди или нет?
Синхронное выполнение блокирует очередь, точнее передаёт управление.
Например, если создать бекграунд очередь и выполнить в ней код асинхронно, будет ожидаемо два потока:
let queue = DispatchQueue(label: "background")
print("isMainThread: \(Thread.isMainThread)") // isMainThread: true
queue.async {
print("isMainThread: \(Thread.isMainThread)") // isMainThread: false
}
А вот если выполнить синхронно, то окажется что это один и тот же поток:
let queue = DispatchQueue(label: "background")
print("isMainThread: \(Thread.isMainThread)") // isMainThread: true
queue.sync {
print("isMainThread: \(Thread.isMainThread)") // isMainThread: true
}
То есть sync как бы возвращает в родительскую очередь (и поток) из любых других, это позволяет избежать race condition например:
let queue0 = DispatchQueue(label: "background1")
let queue1 = DispatchQueue(label: "background2")
let queue2 = DispatchQueue.global()
queue0.async {
print("Thread: \(Thread.current)")
queue1.sync {
print("Thread: \(Thread.current)")
}
queue2.sync {
print("Thread: \(Thread.current)")
}
}
В этом плане последовательная и параллельная очереди практически не отличаются, разве что, если в последовательной очереди (в самой себе) попробовать выполнить код синхронно, будет deadlock:
let queue = DispatchQueue(label: "background")
queue.async {
queue.sync { // <- deadlock
print("Hello")
}
}
В параллельной не будет:
let queue = DispatchQueue.global()
queue.async {
queue.sync {
print("Hello")
}
}
let queue = DispatchQueue.global(qos: .default) queue.sync { queue.async { print(“0”) } print(“1”) print(“2”) print(“3”) }
[/quote] а здесь зачем было сделано сначала sync а затем async?
В том контексте sync никакой нагрузки не несет, можно смело удалять, я лишь хотел подчеркнуть что это другая очередь относительно главной.
Можно ещё вопрос) Например я выношу асинхронно (чтобы главный поток не тормозил) код из main thread как у меня будут выполняться задачи
DispathQueue(label: “new”, attribute: .concurrent).async{
print(“1”)
print(“2”)
}
принты будут выполняться на разных потоках?
или они будут выполнять в разных потоках так
DispathQueue(label: “new”, attribute: .concurrent).async{
DispatchQueue.(label: "new2", attribute: .concurrent).async{
print("1")
}
print(“2”)
}
Не могу понять этого. Или они как то в очереди определённые попадают
Принты в одном блоке (в замыкании если точнее) будут выполняться как обычный код, сверху вниз в одном потоке.
А вот например я:
- я вынес задачи в concerrent асинхронно (в одном замыкании) задачи будут выпонятся по наступлению какого либо сигнала (например отсчёт таймера) или как?
- я выношу синхронно блокируя главную очередь то задачи будут попорядку выполнятся или так же по наступлению какого либо сигнала?
Я понимаю что это не столь важно но мне очень интересно узнать
В литературе ничего про такое нет
Вы хотите познать основы программирования через многопоточность ?
Задачи (выполнение какого то кода) выполняется по очереди, следующая запускается как отработает предыдущая. Когда несколько потоков, несколько задач могут работать одновременно, но соблюдая ту же очередность в своём потоке.