gpt4 book ai didi

objective-c - 单例的线程安全实例化

转载 作者:太空狗 更新时间:2023-10-30 03:08:42 26 4
gpt4 key购买 nike

使用哪种同步方法来确保单例保持单例?

+(Foo*)sharedInstance
{
@synchronized(self)
{
if (nil == _sharedInstance)
{
_sharedInstance = [[Foo alloc] init];
...
}
}
return _sharedInstance;
}

或者使用互斥体?

#import <pthread.h>

static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;

+(Foo*)sharedInstance
{
pthread_mutex_lock(&_mutex);
if (nil == _sharedInstance)
{
_sharedInstance = [[Foo alloc] init];
...
}
pthread_mutex_unlock(&_mutex);
return _sharedInstance;
}

嗯……对此有何评论?

最佳答案

确保您也阅读了关于此问题/答案的讨论。 Why should we separate alloc and init calls to avoid deadlocks in Objective-C?


扩展竞争条件问题; 真正的解决方法是在您的应用程序中不进行不确定的初始化。 不确定惰性 初始化导致的行为很容易因看似无害的更改而改变——配置、“不相关”代码更改等...

最好在程序生命周期中的已知良好点显式初始化子系统。 IE。将 [MyClass sharedInstance]; 放到你的 App delegate 的 applicationDidFinishLaunching: 方法中,如果你真的需要在程序的早期初始化子系统(或者甚至移动它更早一点,如果你想加强防御的话)。

最好还是将初始化完全移出该方法。 IE。 [MyClass initializeSharedInstance]; 如果未首先调用该方法,则 +sharedInstance 断言 ()。

尽管我很喜欢方便,但 25 年的 ObjC 编程经验告诉我,惰性初始化会导致更多的维护和重构问题,而不是它的值(value)。


虽然下面描述的竞争条件存在,但这段代码没有解决下面描述的问题。几十年来,当我们不担心共享实例初始化程序中的并发性时,它就这样做了。留错密码,成就繁荣。

请记住,对于 Colin 和 Harald 的其他正确答案,有一个非常微妙的竞争条件可能会导致您陷入困境。

也就是说,如果正在分配的类的 -init 恰好调用了 sharedInstance 方法,它将在设置变量之前调用。在这两种情况下都会导致死锁。

这是你想要分离分配和初始化的一次。抄袭 Colin 的代码,因为它是最佳解决方案(假设 Mac OS X):

+(MyClass *)sharedInstance
{
static MyClass *sharedInstance = nil;
static dispatch_once_t pred;

// partial fix for the "new" concurrency issue
if (sharedInstance) return sharedInstance;
// partial because it means that +sharedInstance *may* return an un-initialized instance
// this is from https://stackoverflow.com/questions/20895214/why-should-we-separate-alloc-and-init-calls-to-avoid-deadlocks-in-objective-c/20895427#20895427

dispatch_once(&pred, ^{
sharedInstance = [MyClass alloc];
sharedInstance = [sharedInstance init];
});

return sharedInstance;
}

注意 这只适用于 Mac OS X;尤其是 X 10.6+ 和 iOS 4.0+。在较旧的操作系统上, block 不可用,使用锁或执行不基于 block 的操作的各种方法之一。


上述模式实际上并不能防止文中描述的问题,遇到时会造成死锁。问题在于 dispatch_once() 不可重入,因此,如果 init 调用 sharedInstancewedge city.

关于objective-c - 单例的线程安全实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2199106/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com