4
int total = 0;            // these are globals..
BOOL dispatchCalled = NO; //

-(void) callDispatch
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
        dispatchCalled = YES;
        NSLog(@"Total, after 300ms, is %i", total);
    });
}

-(void)play // this is my "main" method..
{
    NSLog(@"app starts running");

    [self callDispatch];

    while(!dispatchCalled)
    {
        total++;
    }

    [self callDispatch];
 }

コンソール :

   2012-08-02 20:36:05.357 MyProject[8245:1a07] app starts running
   2012-08-02 20:36:05.693 MyProject[8245:3d03] Total, after 300ms, is 11513522
   2012-08-02 20:36:05.993 MyProject[8245:3d03] Total, after 300ms, is 11513523

callDispatchで囲まれたメソッドが初めて実行されたとき、whileループは11513522回実行する時間がありました。その時点で、whileループの条件はに設定されYES、whileループはそれ以上実行されないはずです。ただし、ディスパッチ方式条件による更新を確認する前に、もう一度実行されます。何故ですか?

callDispatchで囲まれたメソッドがwhileループと同時に/並列 実行されるためですか?これは、whileループが更新された条件を確認するのにもう1サイクルかかる理由を説明しますか?

4

2 に答える 2

1

はい、同時に実行されています。つまり、ブロックは、条件を通過した後、グローバルをインクリメントする前、またはグローバルをインクリメントした後など、whileループ中の任意の時点で実行される可能性があります。コードを複数回実行すると、totalカウントが一致する場合と一致しない場合があります。(編集:これは、同時に実行するとコードが「非決定的」であることを意味します。)

上記のコードをシリアルキューで実行しようとすると、whileループが無限に実行され、合計が出力されることはありません。シリアルキューでは、callDispatchでスケジュールしたブロックがキューに追加されて次に呼び出されますが、無限ループが終了することはないため、そのキュー内の他のブロックは呼び出されません。

Apple Docの詳細:GCDは3種類のキューを提供します

于 2012-08-02T21:23:17.993 に答える
0

メインイベントループを効果的にロックしている場合、ブロックが実行されているキューはメインキューであってはなりません。

したがって、確実に2つのスレッドが実行されているため、最初のブロックが実行されてから2番目のブロックが実行されるまでにどれだけの時間がかかるかは実際には保証されません。同様に、dispatch_get_current_queue()が非同期キューを取得する場合、その中のブロックの同時実行については何も想定できません。

または、もっと率直に言うと、並行コードでの実行とスケジューリングのパターンについて推論することはできません。「コンピューターをプレイ」して、ある状況で起こったことの概算以外のことを思いつくことはできません。

于 2012-08-02T20:58:35.160 に答える