ios - iOS 上的线程安全惰性初始化

标签 ios thread-safety lazy-loading

我有一个 View Controller ,我想延迟初始化,一旦初始化,尽可能使用相同的副本(我不使用单例,因为我最终想从内存中删除它),我使用 getter 来这样做,我的代码如下所示:

@property (retain) UIViewController *myController

...

@synthesize myController = _myController;


...


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

这可行,但它不是线程安全的,如果在创建对象之前有多个线程评估为真,我就会发生内存泄漏。我尝试过的一种解决方案是 @synchronized 代码,但我不确定这样做的正确方法。

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

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

我想知道是否有其他方法可以实现延迟初始化、线程安全的属性?

最佳答案

这个解决方案有效

请注意,此解决方案仅在第一次在后台线程上访问 myController 时有效。如果在主线程上调用会死锁。

您想使用 gcd。关键是序列化对象的创建,因此无论启动 block 的线程如何,它总是只会被创建一次。

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

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

除非对象为 nil,否则您不会在此处看到性能下降。

由于该属性是隐式原子的,这意味着在 setter 中该值将被自动释放。这应该使其适合与您的自定义获取混合,因为它会自动释放对 _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 方法调用,而不必为原子 setter 重新发明轮子,这很难做到正确。

这个解决方案不起作用

您想使用 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

关于ios - iOS 上的线程安全惰性初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7856733/

相关文章:

javascript - 仅在需要时加载js脚本

ios - DispatchQueue.main.async 阻塞主线程

ios - MKOverlay 路线在 Apple Breadcrumb iOS 代码中工作,但在我的应用程序中不起作用

java - Mysql连接线程是否安全

c# - 使用 MySQL 连接器延迟加载

typescript - redirectTo 基于用户角色的惰性模块

ios - Firebase 和 Crashlytics 委托(delegate)

ios - ios 中的 Tumblr 回调函数

java - Session.sendToTarget() 是线程安全的吗?

database - MapDB 是线程安全的吗?