web-dev-qa-db-ja.com

dispatch_get_global_queueの動作

次のコード:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    for (int i=0; i<100000; i++) {
        NSLog(@"HIGH 1 %d", i);
    }
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    for (int i=0; i<100000; i++) {
        NSLog(@"LOW %d", i);
    }
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    for (int i=0; i<100000; i++) {
        NSLog(@"HIGH 2 %d", i);
    }
});

結果は、高1、高2、低ログの混合になります。

High1とhigh2のログを同時に出力するのはどうしてですか。 high1とhigh2の両方のブログが同じキューにありませんか?それでは、high2ブロックの実行を開始する前に、high1ブロックを終了しないでください。

28
Ashish Awaghad

それはあなたが走っているマシンに依存します。 GCDがグローバルキューのジョブの特定のシステムに十分なスレッドを自動的に作成するため、これをMacで実行していると思います。したがって、おそらく複数のコアがあるため、GCDは両方のコアでジョブを実行しています。

dispatch_queue_createを使用してキューを作成すると、シリアルキューが取得され、FIFOの動作が保証されます。

FWIW(この動作に依存するべきではありませんが)、iPhoneで実行すると、iPhoneがシングルコアであるため、シリアルキューの動作が表示されると思います。ただし、これに依存しないでください。iPad2はマルチコアだと思います。

編集:

dispatch_get_global_queueのドキュメント:特定の優先度レベルの既知のグローバルconcurrentキューを返します。

22
joerick

_dispatch_async_内でスレッドセーフではないメソッドを呼び出すべきではない理由を説明しました。より多くのジョブを実行するのに十分な処理コアがある場合、GCDは先に進み、指定されたキュー内の前のジョブがまだ戻ったかどうかに関係なく、それらに作業を積み上げます。 OS X 10.7では、次のコマンドで独自のキューを作成することで、同じ動作を実現できます。

_dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT);
_

明らかにNSLog()は、不正なアクセスエラーなどを心配することなく、何度でも呼び出すことができますが、スレッドの安全性やジョブが返される順序が心配な場合は、ディスパッチグループの使用を検討してください。

6
Chris Mowforth

dispatch_get_global_queueは、並行処理キューの一種です。high1とhigh2に同じ優先度を指定すると、結果はhigh1とhigh2の混合になります。その後、優先度が低くなるため、結果は低くなります。

0
scorpiozj