0

注意,相关但不相同:iPhone - Grand Central Dispatch 主线程

我在这个问题上失败了很多次,所以这里是源代码:

在主线程上

dispatch_async( dispatch_get_main_queue(), ^{ NSString * str = @"Interrupt myself to do something."} );

我只是好奇,当一个线程切换时,它将其寄存器存储在线程本地存储中,切换上下文,从程序计数器中的新位置运行(我假设它位于程序的副本中,它只是使用不同的堆栈和注册),然后它“返回”到主线程。

当它自己中断时,我只是想知道什么决定什么时候应该中断,以及线程本地的东西会发生什么。

我已经对此进行了一些阅读,但我仍然在思考程序不连续的事实。它们只是“当操作系统决定运行一个进程的一个块或它的块(线程)时小块做的事情。

我是自学成才的,这可能会增加我对注册/汇编知识的缺乏,这可能是任何学者的标准。

谢谢。代码应该有所帮助,这是特定于 iOS 的,但我相信答案/问题与从 main 到 main 的任何语言有关。

由于过去的每一次尝试都导致冗长的答案忽略了我问这个的原因,所以我将最后一次迭代......

这是针对同一线程的。主对主。它真的只是自行停止,将程序计数器移到别处,然后在块处结束吗?此外,这些东西通常不会在分支处改变(if/for 和块)。

将我指向正确的方向也很有效,但就像我说的那样,之前的问题被误读了。

4

2 回答 2

1

如果无法访问 GCD 的内部,很难具体回答您的问题,但一般来说,答案是否定的,简单地向调度队列添加一个工作单元不会立即中断正在执行的代码。

正如您所建议的那样,上下文切换很昂贵,不仅在状态保存和恢复方面,而且处理器将需要转储指令流水线,从而导致浪费周期。

通常操作系统会一直执行当前任务,直到它暂停(例如等待网络或其他 IO 操作)或者可能被某些外部事件(按下手机上的 home 键)中断,但也有时间限制来防止锁定整个设备的失控任务(这是先发制人的多任务处理,而不是任务需要放弃 CPU 的协作多任务处理)

使用 dispatch_async 无法保证与当前代码块相关的代码何时执行。代码块甚至可能不在队列中的下一个 - 其他线程可能在此之前将其他工作单元添加到队列中。

于 2014-08-22T00:06:04.597 回答
0

我认为让您感到困惑的是使用dispatch_async( dispatch_get_main_queue()),它提交代码以在主线程的队列上运行。


在主队列上使用 dispatch_async:

当您调用 时dispatch_async( dispatch_get_main_queue()),它会向主队列添加一个工作单元,该队列从主线程运行它的作业。

如果你从主线程运行这个调用,结果是一样的。该工作被添加到主队列以供以后处理。

当您从主线程进行此调用时,系统不会检查主队列是否有工作要做,直到您的代码返回。

把它想象成一个厨师的厨房。当厨师工作时,他将盘子放在洗碗区。他不会停下来洗碗,直到他目前正在做的事情达到一个临界点。那时,他拿起一盘盘子,将其装入洗碗机,然后继续做饭。

厨师知道每次到了断点他都必须检查碗碟,然后完成洗碗任务,然后再返回烹饪。


在后台队列上使用 dispatch_async:

对后台队列的 dispatch_async 调用就像一个 2 人厨房。有一台洗碗机同时工作。厨师将一盘盘子放入洗碗台(队列),洗碗机(另一个线程)在完成之前的任务后立即接手该任务,而厨师继续烹饪。

以上假设一台具有多个处理器的机器,这是当今的常态。每个处理器可以同时工作,而无需同时处理多个任务。

如果您在具有抢先式多任务处理的单核系统上运行,则将任务提交到单独的线程/后台队列具有与多个处理器相同的效果,但是现在操作系统必须进行杂耍。厨房里只有一个人,但他戴着多顶帽子。该人正在做厨师工作,操作系统大喊“切换!” 厨师记下他在做什么(保存状态),然后跳进洗碗池开始洗碗,一直洗碗,直到操作系统大喊“切换!” 再次,工作人员再次保存状态,切换到下一个角色,并在它离开的地方拿起那个角色(厨师)。

单核系统上的多任务处理成本更高,因为每次工作人员切换角色时,它都必须保存当前状态,然后为另一个角色加载保存的状态,然后继续。这些上下文切换需要时间。

于 2016-12-15T19:24:05.220 回答