从我所读到的关于Grand Central Dispatch的内容来看,GCD并不进行抢占式多任务处理;它只是一个单一的事件循环。我无法理解这个输出。我有两个队列只做一些输出(起初我正在读/写一些共享状态,但我能够简化到这个并仍然得到相同的结果)。
dispatch_queue_t authQueue = dispatch_queue_create("authQueue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t authQueue2 = dispatch_queue_create("authQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(authQueue, ^{
NSLog(@"First Block");
NSLog(@"First Block Incrementing");
NSLog(@"First Block Incremented");
});
dispatch_async(authQueue, ^{
NSLog(@"Second Block");
NSLog(@"Second Block Incrementing");
NSLog(@"Second Block Incremented");
});
dispatch_async(authQueue2,^{
NSLog(@"Third Block");
NSLog(@"Third Block Incrementing");
NSLog(@"Third Block Incremented");
});
我得到以下输出:
2011-12-15 13:47:17.746 App[80376:5d03] Third Block
2011-12-15 13:47:17.746 App[80376:1503] First Block
2011-12-15 13:47:17.746 App[80376:5d03] Third Block Incrementing
2011-12-15 13:47:17.746 App[80376:1503] First Block Incrementing
2011-12-15 13:47:17.748 App[80376:1503] First Block Incremented
2011-12-15 13:47:17.748 App[80376:5d03] Third Block Incremented
2011-12-15 13:47:17.750 App[80376:1503] Second Block
2011-12-15 13:47:17.750 App[80376:1503] Second Block Incrementing
2011-12-15 13:47:17.751 App[80376:1503] Second Block Incremented
很明显,这些块不会以原子方式执行。我唯一的理论是GCD通过NSLog写入stdio会使当前执行等待。我在Apple文档中找不到与此相关的任何内容。谁能解释一下呢?
答案 0 :(得分:8)
GCD不使用任何类型的“事件循环”。它是Mac OS X和iOS最新版本中的一个新内核功能,它实际上没有我所知道的任何其他类似技术。
目标是完成执行您提供的所有代码,就像硬件允许的那样快。请注意,它的目标是最快的完成时间,而不是最快的开始时间。这是一个微妙的差异,但却是一个重要的差异,它会影响它的工作原理。
如果你只有一个空闲的CPU核心,那么理论上一次只能执行其中一个核心。因为单个内核中的多任务比顺序执行两个任务要慢。但实际情况并非如此。如果CPU核心暂时变得空闲或者不是很忙(例如,读取硬盘驱动器,或等待其他程序响应(Xcode绘制NSLog输出)),那么它很可能会继续执行一秒钟GCD项目,因为它正在进行的项目被卡住了。
当然,大多数情况下将拥有多个空闲CPU核心。
它也不一定按照你给出的确切顺序执行。 GCD /内核可以控制这些细节。
对于您的特定示例,Xcode的调试器可能一次只能处理单个NSLog()
事件(至少,它必须一次绘制一个屏幕)。你有两个队列,他们可能会同时开始执行。如果您一次发送两个NSLog()
语句,其中一个语句将等待另一个语句完成。因为除了向Xcode打印东西之外你没有做任何事情,这两个GCD队列将成为第一个将日志数据发送到Xcode的竞赛。第一个有一个轻微的开头,但它是一个非常轻微的,并且通常不足以首先打开与Xcode的连接。
这完全取决于特定纳秒时间硬件上可用的实际硬件资源。你无法预测它,需要适当地构建你的队列以承担一些控制。
答案 1 :(得分:2)
你在哪里读到GCD没有先发制人的多任务处理?我觉得你错了。它建立在系统提供的线程支持之上,因此派遣到队列的GCD块可能会被抢先中断。
您所看到的行为正是我所期待的。第一个和第二个块被分派到同一个队列,因此GCD将确保第一个块在第二个块开始之前完成。但是,块3被分派到一个完全不同的队列(即将在一个单独的后台线程上运行),因此当系统调度线程时,它的输出与其他两个块交错。
答案 2 :(得分:2)
除非您使用串行调度队列,否则您读取的内容都是错误的,所有块都将同时执行。
答案 3 :(得分:0)
您的队列在2个并发后台线程中工作。它们同时提供NSLog消息。当一个线程产生NSlog输出时,另一个线程等待
怎么了?