2013-03-13 34 views
13

、それは言う:重要Grand Central Dispatchでデッドロックを作成するにはどうすればよいですか?アップルのドキュメントで

:あなたは関数に渡す 計画であることdispatch_syncまたは同じキューで実行されているタスクからdispatch_sync_f 関数を呼び出すことはありません。これはデッドロックが発生することが保証されている シリアルキューでは特に重要ですが、並行キューの場合は にする必要があります。

これを行うにはどのようにコードを記述しますか?

+0

あなたがデッドロック作成するコードの例をしたいですか? – Vladimir

+0

はい、学習のために – BlackMouse

+1

現実的な例については、[この質問](http://stackoverflow.com/questions/10330679/how-to-dispatch-on-main-queue-synchronously-without-a-deadlock)も参照してください簡単にデッドロックすることができます。 – zoul

答えて

20

特定のキュー上の意図的なデッドロック:

dispatch_queue_t queue = dispatch_queue_create("my.label", DISPATCH_QUEUE_SERIAL); 
dispatch_async(queue, ^{ 
    dispatch_sync(queue, ^{ 
     // outer block is waiting for this inner block to complete, 
     // inner block won't start before outer block finishes 
     // => deadlock 
    }); 

    // this will never be reached 
}); 

それは、外側と内側のブロックが同じキュー上で動作していることを、ここでは明らかです。これが発生するほとんどのケースは、dispatch_syncの発信者がどのキューを操作しているのかが明白でないところにあります。これは通常、最初に特定のキューで起動されたクラス内のコードを実行している(深く)入れ子になったスタックで発生し、偶然にもdispatch_syncを同じキューに呼び出します。

+0

デッドロック状態のとき... UIが応答しないでください。 – BlackMouse

+2

@ user1251004メインキューがブロックされている場合のみ。 –

+2

この例では、作成された 'queue'だけがブロックされています。メインキューはうまく実行され続けます。 –

7

デッドロックを作成しますシンプルコード:

dispatch_queue_t q = dispatch_queue_create("deadlock queue", DISPATCH_QUEUE_SERIAL); 

NSLog(@"1"); 
dispatch_async(q, ^{ 
    NSLog(@"2"); 
    dispatch_sync(q, ^{ 
     NSLog(@"3"); 
    }); 
    NSLog(@"4"); 
}); 
NSLog(@"5"); 

ログ出力:

1 
5 
2 

ここで内部ブロックは、シリアルキューq上で実行される予定ですが、現在のブロックが終了するまで、それは実行することはできません、しばらく現在のブロックは、それを同期して呼び出すときに内部を待って終了します。

4

ブロックする最も簡単な方法は、現在のキューにdispatch_syncである:

dispatch_sync(dispatch_get_current_queue(), ^{}); 

このブロック現在のキューは、例えば、メインキューシリアルキューです。最新のスウィフト構文で

0

let queue = DispatchQueue(label: "label") 
queue.async { 
    queue.sync { 
     // outer block is waiting for this inner block to complete, 
     // inner block won't start before outer block finishes 
     // => deadlock 
    } 
    // this will never be reached 
} 
関連する問題