ある種のスレッドセーフを適用しないと、複数のスレッドでプロパティを読み書きすることはできません。原則として、文字列のような単純なオブジェクトの場合は、適用atomic
するだけで十分です。アトミック属性と非アトミック属性の違いを参照してください。それが何をするかの詳細については。
率直に言って、私はあまり好きではありませんatomic
。私はそれが何をするかを知っていますが、本当に欲しいものを手に入れるには面倒な方法のようです (そしてしばしばあなたが望むものよりも少なくなってしまいます)。そして、それは非常に一般的な解決策ではありません。atomic
アクセサーを「少し」カスタマイズすることはできません(aなどを追加するsetNeedsDisplay
など)。
そのため、私はキューベースのアクセサーが好きです。少し手間がかかりますが、多くの問題に効果的です。
@property (nonatomic, readwrite, strong) dispatch_queue_t thingQueue;
@property (nonatomic, strong) NSObject *thing;
- (id)init {
...
_thingQueue = dispatch_queue_create("...", DISPATCH_QUEUE_CONCURRENT);
...
}
- (NSObject *)thing {
__block NSObject *thing;
dispatch_sync(self.thingQueue, ^{
thing = _thing;
});
return thing;
}
- (void)setThing:(NSObject *)thing {
dispatch_barrier_async(self.thingQueue, ^{
_thing = thing;
});
}
このシステムで私が気に入っているのは、すべてのリーダーを必要に応じて並行して実行できることです。ライタが更新を行おうとすると、何人のリーダが関係していても、枯渇しないことが保証されます。そして、それはいつもすぐに戻ります。また、値が変更されるキューには明確なポイントがあり、ライターの前に値を要求したリーダーは常に古い値を取得し、ライターの後のリーダーは常に新しい値を取得します。待ち行列に。
重要なのは、ゲッターが同期的であるため、値を取得できるまで待機し、セッターにバリアが含まれていることです。バリアとは、「実行中は、このキューから他のブロックをスケジュールできない」ことを意味します。したがって、多数のリーダー ブロックが並行して実行されていると、セッター バリアが現れて、すべてのリーダーが終了するのを待ちます。次に、値を設定して単独で実行し、その背後にあるリーダーを再び並行して実行できます。