使用dispatch_syncにグランドセントラル派遣
-
25-09-2019 - |
質問
誰でもできるので説明できないう明確な使用例の目的 dispatch_sync
に GCD
ですか。できないかと思います。
よろしく!
解決
あなたはそれを使用します。
この一例は、あなたが同期のために代わりにロックのディスパッチキューを使用しているパターンです。たとえば、あなたがディスパッチキューa
によって媒介アクセスして、共有NSMutableArrayののq
を持っていると仮定します。あなたのフォアグラウンドスレッドが最初の項目をオフに引っ張っている間にバックグラウンドスレッドが(同期)、配列(非同期)に追加することがあります:
NSMutableArray *a = [[NSMutableArray alloc] init];
// All access to `a` is via this dispatch queue!
dispatch_queue_t q = dispatch_queue_create("com.foo.samplequeue", NULL);
dispatch_async(q, ^{ [a addObject:something]; }); // append to array, non-blocking
__block Something *first = nil; // "__block" to make results from block available
dispatch_sync(q, ^{ // note that these 3 statements...
if ([a count] > 0) { // ...are all executed together...
first = [a objectAtIndex:0]; // ...as part of a single block...
[a removeObjectAtIndex:0]; // ...to ensure consistent results
}
});
他のヒント
まずその兄弟を理解してください dispatch_async
//Do something
dispatch_async(queue, ^{
//Do something else
});
//Do More Stuff
あなたが使う dispatch_async
新しいスレッドを作成します。これを実行しても、現在のスレッドは停止しません。つまり、 //Do More Stuff
前に実行される可能性があります //Do something else
仕上げる
現在のスレッドを停止したい場合はどうなりますか?
派遣は一切利用しておりません。普通にコードを書くだけです
//Do something
//Do something else
//Do More Stuff
さて、上で何かをしたいとします。 違う スレッドを実行しながら、あたかも処理が完了したかのように待機します 続けて.
そうする理由はたくさんあります。たとえば、UI の更新はメインスレッドで行われます。
そこで使うのが dispatch_sync
//Do something
dispatch_sync(queue, ^{
//Do something else
});
//Do More Stuff
ここにあります //Do something
//Do something else
そして //Do More stuff
連続してやったとしても //Do something else
別のスレッドで行われます。
通常、別のスレッドを使用する場合、その目的は、待機せずに何かを実行できるようにすることです。大量のデータをダウンロードしたいが、UI をスムーズに保ちたいとします。
したがって、dispatch_sync はほとんど使用されません。しかし、それはそこにあります。私は個人的にそれを使用したことがありません。dispatch_sync を使用するサンプル コードまたはプロジェクトを求めてみてはいかがでしょうか。
dispatch_sync伝統的な相互排他ロックと意味的に等価である。
dispatch_sync(queue, ^{
//access shared resource
});
と同じように動作します
pthread_mutex_lock(&lock);
//access shared resource
pthread_mutex_unlock(&lock);
彼は静かに何であるかシリアルキュー(dispatch_queue_createで渡されたNULLを作成したので、彼の例にのみ動作することを言わないままにするデビッドGelharをDISPATCH_QUEUE_SERIALに等しい)。
あなたが(マルチスレッドパワーのすべてを得るために)同時キューを作成したい場合は、自分のコードが突然変異(removeObjectAtIndex :)あるいは悪いアクセス(範囲外のNSArrayの範囲)の間にあるためにNSArray変異(のaddObject :)のクラッシュにつながるだろう。その場合は、両方のブロックが実行中にNSArrayへの排他的アクセスを確保するための障壁を使用する必要があります。だけでなく、それは実行している間、それはNSArrayの他のすべての書き込みを排除するものでもないが、それも除外他のすべての変更の安全を作り、読み込みます。
同時キューの例は次のようになります:
NSMutableArray *a = [[NSMutableArray alloc] init];
// All access to `a` is via this concurrent dispatch queue!
dispatch_queue_t q = dispatch_queue_create("com.foo.samplequeue", DISPATCH_QUEUE_CONCURRENT);
// append to array concurrently but safely and don't wait for block completion
dispatch_barrier_async(q, ^{ [a addObject:something]; });
__block Something *first = nil;
// pop 'Something first' from array concurrently and safely but wait for block completion...
dispatch_barrier_sync(q, ^{
if ([a count] > 0) {
first = [a objectAtIndex:0];
[a removeObjectAtIndex:0];
}
});
// ... then here you get your 'first = [a objectAtIndex:0];' due to synchronised dispatch.
// If you use async instead of sync here, then first will be nil.
あなたが私のこの質問で実用ルックのいくつかのサンプルが必要な場合:
どのように私はocassionally起こるこのデッドロックを解決しますか
私は私のメインmanagedObjectContextは、メインスレッド上で作成されることを保証することによってそれを解決します。プロセスは非常に高速であり、私は待っている気にしません。手段を待っていない私は、並行性の問題の多くに対処する必要があります。
Iいくつかのコードの必要性は、コードに実行されているものとは異なるスレッドであるメインスレッド上で行われるのでdispatch_sync必要がある。
だから、基本的には、コードがしたい場合は 1.いつものように進みます。あなたは競合状態を心配する必要はありません。あなたは、コードが上を移動する前に完了していることを確認します。 2.別のスレッドで完了
使用dispatch_syncます。
1に違反している場合、使用しdispatch_async。 2に違反している場合だけでいつものようなコードを記述します。
これまでのところ、私だけつまり、何かの必要性は、メインスレッド上で行われるとき、一度これを行うます。
だからここのコードです:
+(NSManagedObjectContext *)managedObjectContext {
NSThread *thread = [NSThread currentThread];
//BadgerNewAppDelegate *delegate = [BNUtilitiesQuick appDelegate];
//NSManagedObjectContext *moc = delegate.managedObjectContext;
if ([thread isMainThread]) {
//NSManagedObjectContext *moc = [self managedObjectContextMainThread];
return [self managedObjectContextMainThread];
}
else{
dispatch_sync(dispatch_get_main_queue(),^{
[self managedObjectContextMainThread];//Access it once to make sure it's there
});
}
// a key to cache the context for the given thread
NSMutableDictionary *managedObjectContexts =[self thread].managedObjectContexts;
@synchronized(self)
{
if ([managedObjectContexts objectForKey:[self threadKey]] == nil ) {
NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
threadContext.parentContext = [self managedObjectContextMainThread];
//threadContext.persistentStoreCoordinator= [self persistentStoreCoordinator]; //moc.persistentStoreCoordinator;// [moc persistentStoreCoordinator];
threadContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
[managedObjectContexts setObject:threadContext forKey:[self threadKey]];
}
}
return [managedObjectContexts objectForKey:[self threadKey]];
}
dispatch_syncは、主に(更新UIのような)メインスレッドでいくつかの操作を実行するdispatch_asyncブロック内で使用されています。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Update UI in main thread
dispatch_sync(dispatch_get_main_queue(), ^{
self.view.backgroundColor = color;
});
});
この半リアルな例です。ご2000zipファイルを分析したい。そのzip図書館のないスレッドセーフです。そのため、すべての作品に触れるzip図書館への出資参画について unzipQueue
キューに挿入します(この例ではRubyですが、すべての電話に直接マッピングされるCライブラリ。"申請"としては、例えばマップ dispatch_apply(3))
#!/usr/bin/env macruby -w
require 'rubygems'
require 'zip/zipfilesystem'
@unzipQueue = Dispatch::Queue.new('ch.unibe.niko.unzipQueue')
def extractFile(n)
@unzipQueue.sync do
Zip::ZipFile.open("Quelltext.zip") { |zipfile|
sourceCode = zipfile.file.read("graph.php")
}
end
end
Dispatch::Queue.concurrent.apply(2000) do |i|
puts i if i % 200 == 0
extractFile(i)
end
私はUIがメインスレッドに戻って変化する信号するとき、非同期ディスパッチ内でディスパッチシンクを使用しました。
私の非同期ブロックが戻って少しだけを保持していると私はメインスレッドがUIを認識している知っているアクションにそれらを変更し、意志。一般的に、いくつかのCPU時間を要するコードの処理ブロックでこれを使用するが、私はまだそのブロック内からアクションUIの変更にしたいです。 UIは、私は信じて、メインスレッド上で動作するようUIは非同期ブロックに変更Actioningすることは無意味です。また、二次非同期ブロックとしてそれらをactioning、または自己の代理人、UIの結果は、わずか数秒後にそれらを見て、それが遅刻見えます。
例のブロック
dispatch_queue_t myQueue = dispatch_queue_create("my.dispatch.q", 0);
dispatch_async(myQueue,
^{
// Do some nasty CPU intensive processing, load file whatever
if (somecondition in the nasty CPU processing stuff)
{
// Do stuff
dispatch_sync(dispatch_get_main_queue(),^{/* Do Stuff that affects UI Here */});
}
});