2011-10-22 18 views
6

私は遅く初期化したい、一度初期化すると、可能な限り同じコピーを使用します(私はシンクトンを使用しません。 、私はそうするゲッターを使用して、私のコードは次のようになります。iOS上でのスレッドセーフな遅延初期化

@property (retain) UIViewController *myController 

... 

@synthesize myController = _myController; 


... 


- (UIViewController *)myController 
{ 
    if (!_myController) {         // Evaluation 
     _myController = [[MyViewController alloc] init]; // Object Creation 
    } 
    return _myController; 
} 

これは動作しますが、それはスレッドセーフではないですし、オブジェクトが作成される前に、複数のスレッドがtrueに評価された場合、私は持っていますメモリリーク私が試みた1つの解決策は、コードを同期させることですが、正しい方法はありません。

これは、動作しているように見えます(lockForMyControllerがシンプルNSStringのである)が、それは多くの、より遅いコードのこのセクションを行います

- (UIViewController *)myController 
{ 
    @synchronized(self.lockForMyController){ 
     if (!_myController) { 
      _myController = [[MyViewController alloc] init]; 
     } 
    } 
    return _myController; 
} 

怠惰な初期化され、スレッドを達成するために他のいくつかの方法がある場合、私は思っていました安全な、財産ですか?

答えて

10

は、このソリューションはmyControllerが初めてスレッド背景にアクセスされた場合は、このソリューションはのみ動作することを

注意を働きます。メインスレッドで呼び出されるとデッドロックします。

gcdを使用します。キーはオブジェクトの作成をシリアライズするので、ブロックを開始するスレッドに関係なく、常に1回だけ正確に作成されます。

ここ
- (UIViewController *)myController 
    if (_myController == nil) { 
     dispatch_sync(dispatch_get_main_queue(),^{ if (_myController == nil) _myController = [[MyViewController alloc] init]; }); 
    } 
    return _myController; 
} 

は、複数のスレッドがブロックを実行しても、ブロックの実行は、メインスレッド上にシリアライズされ、一つだけMyViewControllerが今まで作成することができます。

オブジェクトがnilでない限り、ここでパフォーマンスが低下することはありません。

プロパティは暗黙的にアトミックなので、セッターでは値がオートリリースされることを意味します。これは_myControllerの値の変更をautoreleaseするので、カスタム取得との混合に適しているはずです。

http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW2

しかし、あなたはまだあなたが一つのスレッドに値を設定するが、別の上でそれをアクセスしている競合状態になることがあります。値を設定するときはいつでも、次のようにして、何かをしたいと思うでしょう:

dispatch_sync(dispatch_get_main_queue()、^ {self.myController = {newValueOrNil}});

これは、原子セッターのためにホイールを再開発することなくセッターメソッドの呼び出しをシリアル化することを確実にしますが、これは非常に困難です。

このソリューションは、あなたがGCDを使いたい

動作しません。

http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/c/func/dispatch_once

シングルトンについてのこの記事を参照してください。あなたがシングルトンを望んでいないことは分かっていますが、これはメソッドの使い方を示しています。あなたは簡単にそれを適応させることができます。

Create singleton using GCD's dispatch_once in Objective C

+0

私はそれに慣れています。私はシングルトンのように動作させることができますが、 '[_myController release]を使うと問題があります。 _myController = nil; 'その後、私は' static dispatch_once_t once'変数をリセットすることができないので、再度作成しようとしています。 – Yamanqui

+0

ええと私の質問をうまくいくはずです。 – logancautrell

+0

ありがとう、更新されたソリューションは完全に動作します。 – Yamanqui

関連する問題