1

这是我们项目中的代码范围,我认为它不是线程安全的,因为范围

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

1 回答 1

1

您认为该if块可能会导致问题是正确的。原因如下(来源):

这条线

[[MyHelper alloc] init];

实际上由三个步骤组成:

  1. 分配内存
  2. 将对象构造到分配的内存中
  3. 将静态变量指向分配的内存地址

现在,您会期望这些事情按照 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。

还要检查这个相关的优秀答案

于 2013-05-27T07:51:51.053 回答