背景
以下のコードの意味がずっと分からなかった。
DispatchQueue.main.async {
print("Hello, World")
}
mainキューは直列処理(同期処理)を実行したい時に使用すると耳にした。
それでは、なぜ DispatchQueue.main.sync ではなく、DispatchQueue.main.async なのか。
僕はこれまで、以下のコードと実行結果を見て、
「処理が順番に実行されている!! よし、同期処理成功だ!!」と喜んでいた。
for i in 0...10 {
DispatchQueue.main.async {
print("Start: \(i)")
sleep(1)
}
}
/*実行結果
Start: 0
Start: 1
Start: 2
Start: 3
Start: 4
Start: 5
Start: 6
Start: 7
Start: 8
Start: 9
Start: 10
*/
でも、なぜasync?? syncじゃないの??と思い、DispatchQueue.main.syncにした途端、xcodeからお叱りを受ける。意味がわからなかった。
僕の勘違い
僕は、「ここでの直列処理と非同期処理の実行主体は同じである」という勘違いをしていた。
つまり、DispatchQueue.main.async
は、
「mainキューが直列処理かつ非同期処理を行なうこと」を意味していると思っていた。
ここでの直列処理と非同期処理の実行主体は異なる
以下のコードを実行してみて初めて理解ができた。
for i in 0...10 {
DispatchQueue.main.async {
sleep(1)
print("Start: \(i)")
}
}
print("End")
<僕の予想した実行結果>
Start: 0
Start: 1
Start: 2
Start: 3
Start: 4
Start: 5
Start: 6
Start: 7
Start: 8
Start: 9
Start: 10
End
<実際の実行結果>
End
Start: 0
Start: 1
Start: 2
Start: 3
Start: 4
Start: 5
Start: 6
Start: 7
Start: 8
Start: 9
Start: 10
???
mainキューは直列処理(同期処理)を実行してくれるものじゃないの?
だとすると、これも
for i in 0...10 {
DispatchQueue.main.async {
sleep(1)
print("Start: \(i)")
}
}
これも
print("End")
mainスレッドで実行されるのなら、上から順番に実行されるんじゃないの??
非同期処理と直列処理の意味
そう、ここでのasync(非同期)の意味は、
**「タスクをキューに追加した後、そのタスクの処理完了を待たずに次の行に移行する」**であり、
mainキューの処理の特性であるSerial(直列)とは
「キューに追加されたタスクを、追加された順番に、かつ前タスク処理が終わるのを待ってから処理側へ渡す」
という意味。(ということを理解するのにすごく時間がかかりました。。。)
まとめ
直列キューに非同期でタスクを追加するというのは、
「タスクをキューに追加した後、そのタスクの処理完了を待たずに次の行に移行し(非同期)、
キューは追加されたタスクを、前タスク処理が終わるのを待ってから処理側へ渡す(直列)。」
という意味。
つまりDispatchQueue.main.async
メソッドにおいて、
同期・非同期というのは、**タスクを依頼した人(スレッド)**の動作に関わることで、
直列・並列というのは、**タスクを依頼された人(キュー)**の動作に関わること。
あー、やっと理解できたー。
動作環境
- swift 4.2
- xcode 10.0