2011-06-28 5 views
3

私は、複数のバックグラウンドスレッドから同時にアクセスされるクラスを持っています。私はクラスをコピーすることができません。なぜなら、コンテンツは再作成(処理またはメモリワイズ)する可能性があるからです。スレッドセーフな保持/解放

バックグラウンドでの処理がまだ進行中で、このプロパティにアクセスしているときに、このクラスのプロパティを置き換えることもできます。

現在のところ、私は定期的なリリース/リリースを行っていますが、少なくとも完全にペアであっても、retainCountがランダムに、最終的にはドロップするように見えるため、スレッドセーフではありません(少なくともiOS 4では)このクラスは割り当て解除されます。

このクラスをスレッドセーフにする方法、プロパティの同時アクセスを許可するプロパティの変更を許可する方法の提案を探していますが、プロパティの「以前のバージョン」はバックグラウンドアクション。

+3

-retainCountに依存しないでください:someMethodは、バックグラウンドスレッドで定期的に呼び出されて、あなたのsharedObjectに依存していると仮定し

例、。 –

+0

あなたは何を保持/解放していますか? –

答えて

6

保持および放出は原子である。オートレリーズはできません。保持はスレッド単位であると考えてください。スレッドAがretain(またはretain/autorelease)を保持している場合、スレッドAの参照は、そのretainが均衡するまで(または自動解放プールがなくなるまで)有効になります。

autorelease can neverクロススレッド所有権転送プリミティブとして使用することができます。

これ以外にも、あなたのアプリで何が間違っているのか、さらにコードを書く必要はありません。これは、実行全体であることを保証

@property (atomic, ...) NSString *someValue; // atomic is the default, thus optional 

1

あなたはクラスについて話していますか、それともそのインスタンスですか?

とにかく、保持と解放はドキュメントに従ってスレッドセーフでなければなりません。だからあなたはおそらく別の場所にあるバグを持っているでしょう(これは、iOS 4に依存するかもしれません)。

0

あなたがしようとしているものに十分なはずです。あなたのオブジェクトが2つのスレッド間でアクセスされている場合は、このオブジェクトにアクセスするために通信する必要のある中間地点があり、通常は同じスレッドになります。

例:(スレッドセーフ)あなたの特性がアトミックであることを確認すること

//Thread 1 Object 

//Setting thread 2's object will occur on the same thread so 
//retains and releases will happen in order with no issue 
thread2Object.atomicObject = self.atomicObject; 

だけのプロパティ宣言で非アトミックを入れていないことを意味します。ゲッターやセッターをオーバーライドする場合は、両方をオーバーライドして独自のロック機構(@ synchronize、NSLockなど)を使用する必要があります。

@propert(retain) NSObject *atomicObject; 
0

@propertyはデフォルトである、「アトミック」と宣言することができ、それは結果の一貫性を保証する、マルチスレッドから安全にアクセスすることができます他のスレッドからのコードは、結果の一貫性に影響を与えません。

id val = sharedObject.someValue; 

valの結果は保持され、自動解放されたが、その関係なく、他のスレッドに何が起こるか、valは(自動解放プールが排出される前に)現在の実行ループサイクルの残りのために有効に滞在しません。 valを取得した後、sharedObject.someValueが同じで、別のスレッドがそれを再割り当てできるという保証はありません。

- (void)someMethod { 
    SomeObject *val = sharedObject.someValue; 
    // now, val will remain consistent, 
    // regardless of what happens to sharedObject.someValue 

    [val doSomething]; 
    if (val.someInt > 50) { 
     [val doSomethingElse]; 
    } 
} 
関連する問題