这是我们项目中的代码范围,我认为它不是线程安全的,因为范围
if(sharedHelper)
return sharedHelper;
会引起问题,但我不确定,任何人都可以帮助我吗?
+(id) sharedHelper
{
static MyHelper *sharedHelper = nil;
static dispatch_once_t onceToken;
if(sharedHelper)
return sharedHelper;
dispatch_once(&onceToken,^{
sharedHelper = [[self alloc] init];
});
return sharedHelper;
}
答案 0 :(得分:1)
你认为if
阻止可能导致问题是正确的。这就是原因(source):
这一行
[[MyHelper alloc] init];
实际上由三个步骤组成:
现在,你会期望这些事情从1-3开始。但是,在某些情况下,编译器可能重新排序指令,以便步骤3在步骤2之前发生 -
sharedHelper = // Step 3
operator new(sizeof(MyHelper)); // Step 1
new (sharedHelper) MyHelper; // Step 2
现在,请考虑以下情况:线程1执行步骤1和3并暂停。因此,静态变量指向尚未初始化的内存位置。现在,如果线程2检查if(sharedHelper)
,它会找到一个非NULL地址,并返回该地址。但是等等,这个地址还没有初始化 - 而BAM,你有一个EXC_BAD_ACCESS。
同时检查此相关excellent answer。