- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
使用哪种同步方法来确保单例保持单例?
+(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
调用 sharedInstance
,wedge city.
关于objective-c - 单例的线程安全实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2199106/
我是一名优秀的程序员,十分优秀!