iOS上的线程安全延迟初始化

我有一个视图控制器,我想懒惰地初始化,一旦初始化,尽可能使用相同的副本(我不使用单身,因为我最终要从内存中删除它),我使用getter来这样做,我的代码看起来像这样:

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

这是有效的,但它不是线程安全的,如果在创build对象之前有多个线程求值为true,那么我会发生内存泄漏。 我试过的一个解决scheme是@synchronized的代码,但我不知道正确的方法来做到这一点。

这似乎工作,(lockForMyController是一个简单的NSString),但它使这部分的代码慢很多:

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

我想知道是否有其他的方式来实现一个懒惰的初始化,线程安全的属性?

此解决scheme工作

请注意,只有在第一次在后台线程上访问myController时,此解决scheme才有效。 如果在主线程上调用它将会死锁。

你想使用gcd。 关键是序列化对象的创build,所以无论启动块的线程如何,它总是只被创build一次。

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

在这里,即使多个线程执行该块,该块的执行也会被序列化到主线程上,并且只能创build一个MyViewController。

除非对象为零,否则您不会看到这里的性能。

由于该属性是隐含primefaces的,这意味着在该设置器中该值将被自动释放。 这应该使它适合与你的自定义混合,因为它会autorelease任何值更改_myController。

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}});

这将确保序列化您的setter方法调用,而不必重新发明primefacessetters的轮子,这是很难得到正确的。

此解决scheme不起作用

你想使用gcd。

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

看到这个职位关于单身人士。 我知道你不想要一个单身人士,但是这说明了如何使用这个方法。 你可以很容易地适应它。

在Objective C中使用GCD的dispatch_once创build单例