2012-01-06 18 views
3

どのようにしてオブジェクトセーフティシングルトンオブジェクトを作成するのですか?たとえば。シングルトンオブジェクトである共有データコントローラがある場合、2つ以上のスレッドが同時にそれにアクセスしているとどうなりますか?または、これらのオブジェクトはデフォルトでスレッドの安全性を持っています。スレッドセーフなシングルトンオブジェクト(objective-c?)?

更新

はdatacontrollerのプロパティ内のオブジェクトは、それは、スレッドセーフであるかどうかを決めることを、このシナリオの下でそれをですか..?私のdatacontrollerはNSMutableArrayを持っていて、それは非構造に設定されているのでスレッドセーフではありません。その場合の価値はどうなりますか?

更新:2

そして@synchronized(self)が実際に何をするのか..?

答えて

5

データコントローラは、スレッドセーフされていない場合は、未定義の動作が起こる可能性 - すべてのコストでそれを避ける=)

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 
+0

..私はちょうどここ理論の一部に入っています...あなたはデータコントローラスレッドを作成する方法を示していますいくつかのサンプルコードに私を導くことができます安全... –

+0

システムはpthreadsを提供します - 多くの例が存在します。 NSLockの使用についてiOSとOS Xのサンプルを参照することもできます。サンプルコードよりもロックとスレッドの安全性を実際に説明するので、pthreadサンプルはより良いでしょう。 – justin

+0

もう1つ..あなたは、「NSObjectsはデフォルトではスレッドセーフではありません。アトミックプロパティを使用してもスレッドセーフではありません(これはよくある誤解だからです」)。それでは非原子的なことは何ですか?デフォルトでアトミック? –

-5

は毎回スレッド とする場合をisLockedそのクラスにアクセスしようとすると、次のことを行う必要があります。 私はこれが厳格な交替と呼ばれることを覚えています:)良い古い学校の日。

スレッドA:私は、任意のコードを持っていない

if(!isLocked) { 
isLocked = True; 
Do the stuff 
isLocked = False; 
} 
+1

これはやっていないのです。チェックされたロックは役に立たない。ロックし、操作し、ロックを解除します。 – justin

関連する問題