iOS应用程序中的所有方法通常都在一个线程中吗?(用于防止种族状况)

iOS应用程序中的所有方法通常都在一个线程中吗?(用于防止种族状况),ios,race-condition,Ios,Race Condition,我们可以有许多处理程序:触摸处理程序、UIControl处理程序(按钮、滑块)、performSelector、CADisplayLink、NSTimer事件、手势识别器、加速计处理程序和UIView动画完成块,以及其他一些处理程序 他们都在同一条线上吗?也就是说,它们中只有一个可以同时运行 其他方法或处理程序是否可以成为另一个线程的一部分,从而可以创建争用条件?通常,您会发现iOS上的大多数简单应用程序都会在主线程上执行几乎所有操作。正如您所指出的,当您将多线程引入到图片中时,您会添加另一组需

我们可以有许多处理程序:触摸处理程序、UIControl处理程序(按钮、滑块)、performSelector、CADisplayLink、NSTimer事件、手势识别器、加速计处理程序和UIView动画完成块,以及其他一些处理程序

他们都在同一条线上吗?也就是说,它们中只有一个可以同时运行


其他方法或处理程序是否可以成为另一个线程的一部分,从而可以创建争用条件?

通常,您会发现iOS上的大多数简单应用程序都会在主线程上执行几乎所有操作。正如您所指出的,当您将多线程引入到图片中时,您会添加另一组需要注意的棘手问题。许多开发人员不想为这种增加的复杂性而烦恼,或者通常不熟悉GCD或线程,因此他们避免在后台线程或GCD队列上执行任何操作

您在问题中列出的几个项目涉及到与UIKit的交互,通常这些交互必须发生在主线程上(不过,iOS 4.x增加了在后台执行某些绘图功能的功能)。您在主线程上接收触摸和其他相关事件。如果希望更新接口的大多数方面,安全的方法是在主线程上执行这些更新

通过将计时器(NSTimer、CADisplayLink)附加到在后台线程上运行的nsrunlop,可以在后台线程上激发其更新。你很少看到有人这样做,但这是可以做到的。通常,人们在主运行循环上配置计时器,这会导致回调在主线程上传递

在执行动画时,动画本身将在后台线程上运行(您可以看到,当您使用其他内容阻塞主线程时,动画不会停止),但完成后,您几乎总是会在主线程上收到一个完成块或回调。如果我没记错的话,这其中有一两个例外,苹果的文档中也有这样的说明。在处理可能没有意识到幕后情况的开发人员时,在主线程上触发这些回调是一种安全的方法

综上所述,有很好的理由希望将多线程添加到应用程序中。因为所有的用户界面更新和触摸交互都发生在主线程上,如果你有一些计算成本很高的东西,或者只是需要花费很多时间来执行,如果你在主线程上运行这些东西,你就会看起来冻结了你的应用程序。这是一种糟糕的用户体验,因此您希望将此任务移动到后台线程,以便用户可以在执行此任务时继续与您的应用程序交互。此外,每天都有越来越多的iOS设备带有多个内核,在这些内核之间平衡工作负载并高效使用此硬件需要一定程度的并发处理

人们已经写过关于使代码多线程化的最佳实践的书,您可以在这里找到很多关于这方面的问题,所以我不会详细介绍。我能告诉你的是,你应该阅读苹果公司的,并观看过去两年中有关Grand Central Dispatch的WWDC视频。有了GCD,苹果公司以一种高效且(相对)安全的方式将多线程添加到应用程序中变得更加容易,我鼓励您在自己的应用程序中研究这一点

例如,我有一个开放源码的iOS应用程序,它执行分子结构的详细呈现。我在背景GCD队列上渲染每个帧,因为有时它们需要超过1/60秒的时间来处理,在这些情况下,如果这一切都在主线程上,它们会导致触摸事件被删除,界面结巴。此外,在较新的多核设备上运行时,我发现这样做可以提高40%的性能。为了避免竞争条件,我将与共享数据结构和上下文的交互包装在串行调度队列中,以便无论特定块在哪个线程上运行,一次只能有一个操作使用资源。这只需要添加几行代码,但性能和用户体验方面的好处是巨大的