web-dev-qa-db-ja.com

シリアルキューのdispatch_asyncとdispatch_syncの違いは?

このようなシリアルキューを作成しました。

    dispatch_queue_t _serialQueue = dispatch_queue_create("com.example.name", DISPATCH_QUEUE_SERIAL);

dispatch_asyncの違いは何ですか?

 dispatch_async(_serialQueue, ^{ /* TASK 1 */ });
 dispatch_async(_serialQueue, ^{ /* TASK 2 */ });

そして、dispatch_syncはこのシリアルキューでこのように呼ばれましたか?

 dispatch_sync(_serialQueue, ^{ /* TASK 1 */ });
 dispatch_sync(_serialQueue, ^{ /* TASK 2 */ });

私の理解では、どのディスパッチ方法が使用されているかにかかわらず、TASK 1が実行されてからTASK 2の前に完了します、正しいですか?

118
JRG-Developer

はい。シリアルキューを使用すると、タスクのシリアル実行が保証されます。唯一の違いは、dispatch_syncはブロックが終了した後にのみ戻るのに対して、dispatch_asyncはキューに追加された後に戻り、終了しない場合があることです。

このコードの

dispatch_async(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_async(_serialQueue, ^{ printf("3"); });
printf("4");

2413または2143または1234を印刷できますが、1は常に3の前に印刷されます。

このコードの

dispatch_sync(_serialQueue, ^{ printf("1"); });
printf("2");
dispatch_sync(_serialQueue, ^{ printf("3"); });
printf("4");

常に1234を出力します


注:最初のコードについては、ない print 1324printf("3")がディスパッチされるためafterprintf("2")が実行されます。また、タスクは実行できますafterディスパッチされます。


タスクの実行時間は何も変わりません。このコードは常に12を出力します

dispatch_async(_serialQueue, ^{ sleep(1000);printf("1"); });
dispatch_async(_serialQueue, ^{ printf("2"); });

何が起こったのかも

  • スレッド1:dispatch_asyncシリアルキューへの時間のかかるタスク(タスク1)
  • スレッド2:タスク1の実行を開始
  • スレッド1:別のタスク(タスク2)をシリアルキューにディスパッチします
  • スレッド2:タスク1が終了しました。タスク2の実行を開始
  • スレッド2:タスク2が終了しました。

常に12が表示されます

399
Bryan Chen

dispatch_syncdispatch_asyncの違いは簡単です。

どちらの例でも、TASK 1は常にTASK 2の前に実行されます。これは、前にディスパッチされたためです。

ただし、dispatch_syncの例では、TASK 2がディスパッチおよび実行されるまで、TASK 1をディスパッチしません。これは "blocking" と呼ばれます。コードは、タスクが実行されるまで待機(または「ブロック」)します。

dispatch_asyncの例では、コードは実行が完了するまで待機しません。両方のブロックがキューにディスパッチ(およびエンキュー)され、残りのコードはそのスレッドで実行を継続します。その後、将来のある時点で(キューにディスパッチされたものに応じて)、Task 1が実行され、次にTask 2が実行されます。

18
Dave DeLong

それはすべてメインキューに関連しています。 4つの順列があります。

i)シリアルキュー、非同期ディスパッチ:ここでタスクは次々に実行されますが、メインスレッド(UIへの影響)は戻りを待機しません

ii)シリアルキュー、ディスパッチ同期:ここでタスクは次々に実行されますが、メインスレッド(UIへの影響)に遅れが表示されます

iii)同時キュー、非同期ディスパッチ:ここで、タスクは並行して実行され、メインスレッド(UIへの影響)は戻りを待たずにスムーズになります。

iv)同時キュー、ディスパッチ同期:ここでは、タスクは並行して実行されますが、メインスレッド(UIへの影響)に遅延が表示されます

同時キューまたはシリアルキューの選択は、次のタスクの前のタスクからの出力が必要かどうかによって異なります。前のタスクに依存している場合は、シリアルキューを採用するか、並行キューを使用します。

そして最後に、これはビジネスを終えたときにメインスレッドに戻る方法です:

DispatchQueue.main.async {
     // Do something here
}
3
rd_