データコントローラは、スレッドセーフされていない場合は、未定義の動作が起こる可能性 - すべてのコストでそれを避ける=)
NSObjectsは間違いなく、デフォルトではないスレッドセーフです。アトミックプロパティを使用しても、スレッドセーフではありません(これはよくある誤解のため追加されています)。
典型的な解決方法は、すべての変更可能状態が適切なロック(mutexまたは@synchronized
など)で保護されていることを確認することです。
私が可変状態と言うとき、私は外部または内部で変異を起こすことができるオブジェクトを指しています。わからない場合は、型を複数のスレッドから読み書きするようにロックしてください。これは、常に読み書きが行われる必要があります。あなたが多くの読書をしているならば、読書のためのロックはより良い、より特殊なロックかもしれません。
詳細については、いくつかのコードを投稿する必要があります。それはdatacontrollerのプロパティ内のオブジェクトは、それは、スレッドセーフであるかどうかを決定することを、このシナリオの下で
更新
ですか..?私のdatacontrollerはNSMutableArrayを持っていて、それは非構造に設定されているのでスレッドセーフではありません。その場合の価値はどうなりますか?
推移的であると考えてください。 NSMutableArray、保持するオブジェクト、およびそれらへのすべての外部参照は、スレッドセーフな方法で使用する必要があります。すべてを追跡する必要があります。通常は、共有する可変状態を減らすことから始めます。クライアントに配列への参照を与えるのではなく、配列に保持されている要素のコピーを与えます。一方、すべての読み取り、書き込み、および要素のコピーをロックで保護します。簡単にするために
、私は@synchronize
を使って紹介します:
@interface MONCookie : NSObject <NSCopying>
- (NSString *)name;
@end
@interface MONDataController : NSObject
{
@private
NSMutableArray * cookies; // << MONCookie[]
}
- (void)addCookie:(MONCookie *)cookie;
- (MONCookie *)cookieWithName:(NSString *)name;
@end
@implementation MONDataController
- (id)init
{
// no lock required here
self = [super init];
if (nil != self) {
cookies = [NSMutableArray new];
}
return self;
}
- (void)dealloc
{
// no lock required here
[cookies release], cookies = nil;
[super dealloc];
}
- (void)addCookie:(MONCookie *)cookie
{
@synchronized(self) { // now accessing cookies - lock required
[cookies addObject:cookie];
}
}
- (MONCookie *)cookieWithName:(NSString *)name
{
MONCookie * ret = nil;
@synchronized(self) { // now accessing cookies - lock required
for (MONCookie * at in cookies) {
if ([at.name isEqualToString:name]) {
ret = [at copy]; // << give them a copy if cookie is not threadsafe
}
}
}
return [ret autorelease];
}
@end
アップデート2
@synchronized
オブジェクト・レベルのロックを設定します。あなたのインスタンスに帰属する再帰(または再入可能)ロックと考えることができます。他のロック方法と比較してもかなり遅いです。上記のコードはそれを使用しており、スレッドセーフであり、再帰的なロックを保持し、@synchronized
の境界でロックおよびロック解除することと同等です。私はあなたがブールのようなあなたのシングルトンオブジェクトで共有ブール変数を置くべき 、私の知る限りは、オペレーティングシステムのコースから知っているよう 前に、客観Cでプログラムが、していない
@interface MONCookie : NSObject <NSCopying>
{
@private
NSRecursiveLock * lock;
}
@end
@implementation MONCookie
- (id)init
{
self = [super init];
if (nil != self) {
lock = [NSRecursiveLock new];
}
return self;
}
- (void)temperatureDidIncrease
{
// ...
}
- (void)bake
{
// use the same lock for everything
// do not mix @synchronized in some places, and use of the lock
// in others. what you use to protect the data must remain consistent
//
// These are equivalent approaches to protecting your data:
{ // @synchronized:
@synchronized(self) {
[self temperatureDidIncrease];
}
}
{ // using the lock:
[lock lock];
[self temperatureDidIncrease];
[lock unlock];
}
}
@end
..私はちょうどここ理論の一部に入っています...あなたはデータコントローラスレッドを作成する方法を示していますいくつかのサンプルコードに私を導くことができます安全... –
システムはpthreadsを提供します - 多くの例が存在します。 NSLockの使用についてiOSとOS Xのサンプルを参照することもできます。サンプルコードよりもロックとスレッドの安全性を実際に説明するので、pthreadサンプルはより良いでしょう。 – justin
もう1つ..あなたは、「NSObjectsはデフォルトではスレッドセーフではありません。アトミックプロパティを使用してもスレッドセーフではありません(これはよくある誤解だからです」)。それでは非原子的なことは何ですか?デフォルトでアトミック? –