質問: DispatchQueue(label: "utility", qos: .utility) dispatchQueue.async { print("A") DispatchQueue.main.async { print("B") } print("C") } ``` 特に知りたいのは、mainスレッドの中にutilityがある場合、utilityの処理の記述に到達するとmainスレッドが終了してutilityに切り替わるのかどうかという点です。 print("A")とprint("C")が優先されて、print("B")は後回しになるのでしょうか? 全部mainスレッドとして処理するとか、全部utilityとして処理するのは分かりやすいですが、複数のDispatchQueueが組み合わさった場合にどの様な処理が行われているのかが分かりません・・・。 DispatchQueueの計算順序によってクラッシュが引き起こされたり、引き起こされなかったりが起こるとしたらどの様なパターンがあるのかなど知りたいです。
回答: 結論から言うと、2つの別々のキューで実行される処理のどちらがどんな順番で処理されるかは、(明示的な同期のための処理を行わない限り)不定であり、特定の順序に依存するような処理を書いてはいけません。 ### //mainスレッドの中にutilityがある場合 * `print("C")`は`print("A")`の後に実行されます * `print("B")`は`print("A")`の後に実行されます ### //utilityの中にmainスレッドがある場合 * `print("C")`は`print("A")`の後に実行されます * `print("B")`は`print("A")`の後に実行されます どちらの場合でも、`print("B")`と`print("C")`の実行順序は **不定** です。 > > DispatchQueueの計算順序によってクラッシュが引き起こされたり、引き起こされなかったりが起こるとしたらどの様なパターンがあるのかなど知りたいです。 > > > 一番多いのは、スレッドセーフではないオブジェクト(例えばSwiftの`Array`)を複数のスレッドから同時にアクセスしてしまう場合でしょう。(片方のスレッドでは読み込みだけしか行わないと言う場合でもダメ。) このような場合には、同時アクセスが絶対に起こらないような制御をしてやらないといけません。 ただ、この種のマルチスレッドがらみのデバッグは非常に大変で、テスト方法によっては何万回テストしても、不具合を再現できない場合もあります。 実行順序が「不定」と言うのは、ランダムに順序が変わると言う意味ではなく、予測不可能ないくつもの要素によって実行順序が変わってしまうためで、テスト方法によっては単に「たまたまうまくいっているだけ」と言うのが繰り返されるだけになります。 日頃から、同時アクセスが起こらないようにするための基本的なパターンを身につけるようにしないといけません。あなたの例でいうと、`print("B")`の位置と`print("C")`の位置で、同一のスレッドセーフではないオブジェクトにアクセスしてはいけません。