iOS中的线程安全

线程基础

当您的应用程序首次启动时,iOS将创建一个新进程,并为此应用程序进程分配内存。 简而言之,一个应用程序进程的内存由三个块组成。

程序存储器存储目标C或快速编译的代码的机器指令。

存储使用swift的init()方法或Objective-c的[…alloc] init]创建的对象。

堆栈是用于方法调用的内存区域。 方法将其参数和局部变量存储在堆栈中。

默认情况下,一个应用程序进程由一个线程(主线程)组成。 如果您的iOS应用使用多个线程,则所有线程共享程序内存堆,但是每个线程都有自己的线程 指令指针(IP) 堆栈 。 这意味着每个线程都有自己的程序流,并且如果在一个线程上调用方法,则其他任何线程都无法看到参数和局部变量。 但是在堆上创建的对象可以被所有线程看到,访问和操纵。

现在,让我们创建一个简单的程序。 打开Xcode并创建一个新项目。 创建一个名为“ Foo ”的类,如下所示:

如我们所见,并非所有线程都按预期输出值9(如果您的执行产生正确的结果-所有线程上的值为 9,请重新执行它,直到产生错误的结果为止。肯定会。)

为什么所有线程都无法产生正确的结果? 好吧,因为我们的程序不是线程安全的。

正如我们在上面看到的, doIt方法不是线程安全的,因为它在多线程环境中不会产生与在单线程环境中相同的结果。

但是,这种行为可能是什么原因呢? 如前所述,每个线程都有自己的指令指针( IP 堆栈 但是所有线程共享 Foo课以来 实例在堆上分配,并且在所有线程之间共享,这就是为什么所有线程都会干扰doIt方法的原因 执行。

让我们仔细看看这种干扰。 我们考虑在两个线程Thread-1Thread-2上执行doIt方法: