2013-09-04 21 views
10

ブロック内でdispatch_async()を呼び出すと、@synchronized()を使用してIOSのロックがどうなりますか? EXのために同期ブロックとdispatch_async

id myID 
-(void) foobar 
{ 
    @synchronized(myID){ 
     dispatch_async(){ //do stuff with myID}; 
    } 
} 

はロックがdispatch_asyncコール内でまだ有効ですか?もっと重要なのは、dispatch_async()の中で別の@synchronized()コールを使用することに欠点があるかどうかです。

+0

達成しようとしていることは何ですか? – Wain

+0

ところで、あなたは、いつでもmyIDを再インスタンス化していないと仮定して正しいですか? '@synchronized'ブロックは、一般的な変数ではなく、' myID'が指すオブジェクトのその特定のインスタンスに固有のものです。 – Rob

答えて

3

ロックは、2つの異なるブロックが一度にディスパッチされることを防ぎます。しかし、それらは非同期的にディスパッチされるので、それらは実行されてもよいし、将来的には任意に実行されてもよい。ディスパッチコールも完了するのを待つことはありません。

ブロック内のものは同期されていません。最小限の変更で達成するためのオプションは、同期ディスパッチか、ブロック内での同期のみです。

あなたがやっていることに応じて、シリアルディスパッチキューを確立し、それにブロックをディスパッチすることをお勧めします。

8

バックグラウンドキュー内のこのmyIDオブジェクトとの対話を同期しようとしている場合は、逆の方法で、ディスパッチされたブロック内のロックが必要です。今あなたが持っている:あなたのキューに派遣ブロックを追加するプロセスを同期だが、はあなたがバックグラウンドでやっている同期しない

@synchronized(myID) { 
    dispatch_async(queue, ^{ 
     // do stuff with myID 
    }); 
} 

。私はそれがあなたが意味するものではないと思う。

おそらく意図:

dispatch_async(queue, ^{ 
    @synchronized(myID) { 
     // do stuff with myID 
    } 
}); 

をそれは非常に似ていますが、全く異なる動作が発生します。現在、バックグラウンド・キューにディスパッチされた作業は同期されています。さらなる改良として

、これはブロックはおそらく遅いです(と私はそれがかもしれ仮定)派遣なら、あなたはおそらくできるだけ多くの@synchronizedブロック制約したいと思います:あなたの場合は

dispatch_async(queue, ^{ 

    // do slow stuff in preparation for interacting with `myID` 

    @synchronized(myID) { 
     // quickly do stuff with myID 
    } 

    // do anything else here 
}); 

@synchronizedブロック内のすべてのバックグラウンドブロックを実行すると、それをバックグラウンドにディスパッチする目的、つまりメインキューへの影響を最小限に抑えるために、すべての目的を無効にすることができます。この最後の演出は、その問題を緩和する。

最終的には、シリアル・キュー(またはバリアで更新を行う非グローバル・コンカレント・キュー)を使用している場合は、ロックの必要性を排除する技術としてよく使用されています。 myIDのすべての更新と照会がそのキューにディスパッチされます。 「並行処理プログラミングガイド」のEliminating Lock-Based Codeを参照してください。

+0

「メインキューへの影響を最小限に抑える」と言えば、バックグラウンドプロセスが長くかかるということだけですか?作業はまだバックグラウンドキューで実行されており、作業は完了していません。 UIをブロックします。 – Ixx

+0

@Ixx - いいえ、私の主張は、(a)バックグラウンドスレッドの '@synchronized'ブロックの中で何か時間を費やす場合です。 (b)メインスレッドも 'myID'にアクセスする必要がある(したがって' @synchronized'も使わなければならない)場合、バックグラウンド '@ synchronized'ブロックはメインスレッドを簡単にブロックして、これをディスパッチする目的を破りますバックグラウンドのキューにすべてのもの。したがって、バックグラウンドスレッドが '@synchronized'をしなければならない時はできるだけ速やかに出入りし、できるだけ時間のかかるものを' @synchronized'ブロックの外に置いてください。 – Rob

関連する問題