2017-02-03 17 views
1

私は、5人のシリアルディスパッチキューを使用するいくつかのiOSコードを移植しようとしているAndroidエンジニアです。私は正しいことを考えていることを確認したい。dispatch_queuesと同期/非同期ディスパッチの理解

  • SERIALキューにdispatch_syncは、基本的には唯一つのスレッドがアクセスすることができ、実行されますブロックは重要な領域であると考えることができる同期queue-としてキューを使用しています。これは、別のスレッド上のブロックを行うシリアルqueue-に

    get_semaphore() 
    queue.pop() 
    do_block() 
    release_semaphore() 
    
  • dispatch_asyncのその等価スレッド電流に直ちに起こるとすぐに、現在のスレッドのリターンをすることができます。しかし、シリアル待ち行列のため、これらの非同期スレッドのうちの1つだけが一度に実行されることを約束します(次のdispatch_async呼び出しは、他のすべてのスレッドが終了するまで待機します)。そのブロックはクリティカルな領域と考えることもできますが、別のスレッドで発生します。上記と同じコードですが、最初にワーカースレッドに渡されます。

私はそれをオフにしていますか、それとも正しく把握しましたか?

答えて

1

これはあまりにも複雑な考え方のように感じられますが、その説明の詳細はほとんど正しくはありません。具体的には、「現在のスレッドですぐに発生する」というのは正しくありません。

まず、戻ってみましょう。dispatch_asyncdispatch_syncの区別は、現在のスレッドがそれを待っているかどうかだけです。しかし、シリアル・キューに何かをディスパッチするときは、GCD自身が選択した別のワーカー・スレッド上で実行されていると常に想像してください。はい、最適化として、時々dispatch_syncは現在のスレッドを使用しますが、あなたはこの事実を保証するものではありません。

第2に、dispatch_syncについて議論するとき、あなたは「すぐに」実行していると言います。しかし、それは決して確実ではありません。あるスレッドがあるシリアルキューに対してdispatch_syncを実行すると、そのスレッドは(a)そのシリアルキューで現在実行中のブロックが終了するまでブロックします。 (b)その直列待ち行列の他の待ち行列ブロックを実行して完了させる。明らかに、スレッドA自身がディスパッチしたブロックが実行されて完了します。

同期のためにシリアルキューを使用すると、メモリ内のオブジェクトへのスレッドセーフなアクセスが頻繁に発生するため、同期処理が非常に高速になるため、待機スレッドは一般に無視されます。そのディスパッチされたブロック(および以前のディスパッチされたブロック)は終了する。しかし、一般に、すぐに実行されると言うのは間違いです。 (常にすぐに実行できる場合は、アクセスを同期させるためのキューは必要ありません)。


私はあなたがスレッドセーフか、そのようないくつかの他の理由を確実にするためには、でなければならない、コードの一部のビットの話をしていると仮定する「臨界領域」に関するご質問の交渉は、同期。したがって、このコードを実行して同期させる場合、唯一の質問dispatch_syncdispatch_asyncの違いは、現在のスレッドが待機する必要があるかどうかです。たとえば、あるモデルにdispatch_asyncが書き込まれる可能性があります(処理を続行する前にモデルが更新されるのを待つ必要がないため)dispatch_syncは一部のモデルから読み込みます(明らかに進めたくないので読み取り値が返されるまで)。

シンク/非同期パターンのさらなる最適化は、リーダライタパターンであり、同時読み取りは許可されていますが、同時書き込みは許可されていません。したがって、並行キューdispatch_barrier_asyncを使用して書き込み(書き込みの場合はシリアルのような動作を実現)を行いますが、dispatch_syncの場合は他の読み取り操作と並行してパフォーマンスが向上します。

+0

クリティカルリージョンは、クリティカルセクションの別の名前です。https://en.wikipedia.org/wiki/Critical_section –

+0

はい、それはあなたが意味すると思ったものです。 iOSでは、これを「同期」する必要があると言います。 [Threading Programming Guide:Synchronization](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW1)を参照してください。 )。しかし、これはGCDの前にあります。これについては、「同時プログラミングプログラミングガイド:ロックベースのコードを削除する」(https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/ThreadMigration/ThreadMigration.html#//apple_ref/doc/uid/TP40008091-CH105-SW3)。 – Rob

+0

うん。だから、私は即座に物事を語ることに少しうんざりでしたが、私はそれが正しいことをしていた。幸いにも私は、Androidの実装のためのメッセージキューを1つに減らすことができると考えています。 –

1

nitsを選択する場合、dispatch_syncは必ずしも現在のスレッドでコードを実行するとは限りませんが、そうでない場合は、タスクが完了するまで現在のスレッドをブロックします。この区別は、スレッドIDまたはスレッドローカルストレージに依存している場合にのみ重要です。

しかし、そうでなければ、私は微妙なものを逃していない限り、はい。

+0

お役立ち情報改訂された答え。 – dgatwood