2011-07-19 9 views
11

私はキューがループしている間、短期間待ちます。私は自分のオプションを考えており、キューを再開するのをテストしていましたが、それはいくつかの可動部分を必要とするようです。だから、代わりに睡眠や睡眠を使うことを検討しています。それは一般的なスレッディング機能のほうが多く、スリープを避けて、GCDオプションをつけて待ち行列を一時停止させるべきかどうかを知りたいと思っています。Grand Central Dispatchキューでスリープを使用しない理由はありますか?

私は関連する1つの質問を見つけましたが、その答えは彼がインクルードを欠いていたことを示しています。スリープコールをGCDキューと混在させることに何か懸念はありますか?

iphone - is it ok to use usleep on a secondary thread on Grand Central Dispatch?

+2

通常、スリープループは、再考が必要なデザインの指標とみなされます。ポーリングではなく、準備が整ったときにスレッドに通知することができない理由はありますか? – drekka

+0

@Derek - それはポーリングではないかもしれませんが、例えば、少なくとも50msごとに起こるものです。それは少なくとも私の前提ですが、良い質問です。 :) –

+0

@James Black: 'dispatch_after'(そして友人)がその問題を解決するのにもっと適していますか? –

答えて

7

あなたがメインスレッドを拘束することはありませんように、あなたが睡眠を使用することができますが、あなたが述べたように、メインスレッドのオフにそれを行います。

しかし、小さな睡眠が必要な場合は時間が正確ではない可能性がありますが、それ以外の場合は睡眠量の後に少なくとも覚醒しますCPU。

しかし、少なくともスリープを使用すると問題は発生しません。これは、少なくとも他のスレッド/アプリケーションに実行可能なチャンスを与えるためです。

+0

ありがとう、私は非同期を実行しているキューですべての作業を維持しています。必要に応じてメインスレッドでキューを実行します。私はAudio Unitコールバックでオーディオを処理しているので、Objective-Cオブジェクトなしでコレクションを管理できるように、変数、特にAudioBufferListを多くのインスタンスを収集する必要があり、それを構造体にする必要があります。今私は、どのようにそれらのABLインスタンスをすべて保持し、安全にリリースするかを理解する必要があります。 – Brennan

+0

時にはメインスレッドを結んでいることがあります。たとえば、NSOutlineViewはアイテムの子を展開するときに素敵なアニメーションを表示しますが、バックグラウンドスレッド(ユーザーが展開した後)で子をフェッチすると、任意のアニメーション。だから、私はバックグラウンドスレッドを起動し、その後、メインスレッドを瞬時にブロックし、バックグラウンドスレッドがすでに終了していれば、NSOutlineViewが要求したアイテムを返します。スレッドがまだ進行中の場合、私は何らかの "..."値を返し、バックグラウンドが完了したらリロードするように指示します。 –

+0

@AbhiBeckert - 私は別の解決策を探しています。UIスレッドを縛ると、何かをしようとしているのに応答がないので、ユーザーに悲しみを引き起こす可能性があります。 –

1

Grand Central Dispatchでスリープを使用すると、GCDによってスレッドがプールされ、別のジョブでスレッドが使用されないようにするため、問題が発生することがあります。 GCDは原因によってスレッド数を増やすことができますが、私はこの状況では睡眠を避けることができますが、それは状況によって異なります。

+1

gdcキューをスリープ状態にすることは、より多くの依存性と問題だけで、独自のスピンロックを作成するようなものです! –

+0

この1つのタスクだけを実行する1つのキューをスリープ状態にする必要がある場合はどうすればよいですか?私はこのキューで多くのタスクを実行していません。キューを一時停止/再開しようとしましたが、動作していないようです。 GCDキューを適切に待機させる良い例を見直したいと思います。 – Brennan

+0

私はそれが寝るのが間違っている理由を考えることはできません、それはちょっとひどいようです。それをスピンロックと比較することは、まったく公平ではなく、スリープでCPUサイクルを使用していないため、スピンロックによって引き起こされる他の問題である、CPUがキャッシュからコードをフラッシュするのを妨げていません。 –

10

この問題は、長年にわたって私に悲しみの多くを引き起こしているので、私は経験に苦しんでいる の利益を共有したいと考え出し:

あなたは(sleepを呼び出す含む)をブロックの任意の時間を仕事にユニット*をGCDに提出すると、スレッドスターベーションの可能性のある状況が発生しています。さらに、作業単位のブロッキングが同期プリミティブ(すなわちセマフォ、ロックなど)の使用によるものである場合、またはこれらのプリミティブを使用して複数の作業単位がインターロックされている場合、スレッドスターベーションはデッドロックを引き起こす可能性があります。分でよりますが、ここではショートバージョンです:あなたはGCDに提出作業単位でブロックすると

は:

  • せいぜい、あなたは非効率的GCDを使用しています。
  • 最悪の場合、あなたは の飢餓の可能性、そして(潜在的に)デッドロックの可能性にさらされています。

理由は次のとおりです。OSにプロセスごとのスレッド制限があります。プロセス単位のスレッド制限を変更することは不可能ではありませんが、現実的にはそれほど価値はありません。 GCDには、独自のキュー幅制限(同時キューにサービスするために使用するスレッド数)があります。 (詳細は複雑ですが、ここでは、複数の並行キューを作成すると、一般的にこの制限を回避することはできません)。定義上、GCDの制限はプロセスごとのスレッド制限よりも低くなっています。さらに、GCDのキュー幅の制限は、文書化されていない実装の詳細です。経験的には、OS Xのこの記事の執筆時点では、限界が64であるように見えました。この制限は文書化されていない実装の詳細なので、それが何であるかを知ることはできません。 (パブリックAPIを使用して変更することもできません)理想的に言えば、GCDがキューの幅の制限を1に変更した場合でも、コードは完了するまで実行されるように記述する必要があります。(また、同じスレッドがメインスレッドである場合でも同じことが当てはまるはずですが、それはタスクを不必要に難しくし、少なくとも1つのバックグラウンドスレッドが常に存在すると想定するのは安全です。 GCDを使っていないとGCDを使う価値はほとんどありません)。

どうやってやりますか? I/Oを待つ間にブロックしている場合は、dispatch_ioファミリーの呼び出しを使用するようにコードを移行することを検討してください。準ビジー待機状態(元の質問)の場合は、一定時間後に何かを確認するためにdispatch_afterを使用できます。それ以外の場合は、ディスパッチタイマーやディスパッチソースが適切かもしれません。

私は、GCDに提出された作業単位で完全にブロックされないようにすることは必ずしも実用的ではないことを認めた最初の人です。さらに、GCDとObjective-Cのブロック構文を組み合わせることで、ブロッキング/同期操作をバックグラウンドスレッドに移動することでUIスレッドをブロックする状況を回避するための、表現が簡単で読みやすいコードを書くことが非常に簡単になります。開発の迅速化の面では、このパターンは非常に役立ち、私はいつもそれを使用しています。つまり、GCDを使用して作業単位をエンキューすると、ブロック化された実装の詳細なことがわかります実際には制御することはできません(パブリックAPIを使用してGCDのキュー幅を設定/変更することはできません)。

忙しい待ち時間sleepまたはusleepを呼び出す)は、のうちの1つで、が避けられ、は少なくとものGCDに提出された作業単位でブロックできます。私はさらに進んで、が常にであるという大胆な声明を、GCDワークユニットで忙しく待って実行できるあらゆる操作を実装するために、より迅速に開発することができます。

* "作業単位"を使用してObjective-Cブロックや関数ポインタ/引数を参照してGCDに実行依頼して、作業 "ブロック"との混乱を制限しています。あなたのスレッドがカーネルに中断されています "。

関連する問題