我正在阅读一本iOS书,上面写着“dispatch_sync函数阻塞了块提交的并发队列,即它使队列等待” . 基于这个概念,我创建了自己的示例,如下所示 . 以下片段写在“viewDidLoad”方法中
dispatch_queue_t concQueue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
void (^secondBlock)(void) =^( void)
{
//Second Block
for (int count=0; count<1000; count++)
{
if( [NSThread currentThread] == [NSThread mainThread ] )
{
NSLog(@"2 block main Thread") ;
}
else
{
NSLog(@"2 block other THREAD") ;
}
}
};
void (^firstBlock)(void) =^( void)
{
//First Block
for (int count=0; count<100; count++)
{
if( [NSThread currentThread] == [NSThread mainThread ] )
{
NSLog(@"1 block main Thread") ;
}
else
{
NSLog(@"1 block other THREAD") ;
}
}
dispatch_sync(concQueue1, secondBlock) ;
};
dispatch_async(concQueue1,firstBlock);
//Making the main thread sleep for some time
[NSThread sleepForTimeInterval:0.1] ;
dispatch_async( concQueue1, ^(void) {
//Third Block
for (int count=0; count<1000; count++)
{
if( [NSThread currentThread] == [NSThread mainThread ] )
{
NSLog(@"3 block main Thread") ;
}
else
{
NSLog(@"3 block other THREAD") ;
}
}
});
我让主线程休眠了一段时间,以便“第一个块”中的dispatch_sync函数被执行 . 我得到的输出就是这个 . 我正在展示输出的一部分 .
GCDExamples[2459:554259] 2 block other THREAD
.
.
.
GCDExamples [2459:554259] 2阻止其他线程
GCDExamples[2459:554256] 3 block other THREAD
GCDExamples [2459:554256] 3阻止其他线程
GCDExamples [2459:554259] 2阻止其他THREAD //Point firs t
GCDExamples [2459:554256] 3阻止其他线程
关于输出的一些要点:“ 3 block other THREAD ”和 "2 block other THREAD 中显示的输出是该输出线的第一次出现
MY QUESTION: 根据概念,因为dispatch_sync函数一旦第二个块启动,它应该使队列等待而不是允许"Third block"启动 . 但是如前面的输出所示"2 block other THREAD"在 "//Point first" 之后的"3 block other THREAD"语句后面显示 . 这表明dispatch_sync函数没有使队列等待 . 怎么可能?如果需要的话,请问我另外的其他信息 .
EDIT 1 : 我在这里提出这本着名书籍的文字来解释我的观点 . 这本书是"iOS 7 Programming cookbook" . 文本如下: - “对于任何不涉及UI的任务,您可以在GCD中使用全局并发队列 . 这些允许同步或异步执行 . 但同步执行并不意味着您的程序在继续之前等待代码完成 . It simply means that the concurrent queue will wait until your task has finished before it continues to the next block of code on the queue. When you put a block object on a concurrent queue, your own program always continues right away without waiting for the queue to execute the code. 这是因为并发队列,顾名思义,在主线程以外的线程上运行代码 . “
正如粗体文本所说,并发队列将等待UNTIL我的任务完成后再继续下一个块 . 我的块打印“2 block other THREAD”应该允许在“3 block other THREAD”开始之前完成,但不是这样的情况我的“2 block other THREAD”再次打印与“3 block other THREAD”语句混合时事实上我的所有“2挡其他线程”应该被允许完成然后“3挡其他线程”应该跟随 . 评论是否需要更多信息 .
2 回答
如果这就是这本书的内容,那就把它扔掉吧 . 那是错的 .
同步与异步是关于调用者 . 当某些代码调用
dispatch_sync()
时,在调度的任务完成之前,该代码无法继续 . 队列未被阻止或被迫等待或类似的事情 .相反,当代码调用
dispatch_async()
时,任务被放入队列,调用者继续执行下一步 . 它不会等待发送的任务开始,更不用说完成了 .这与队列是并发还是串行完全不同 . 这种区别属于队列和它们运行的任务,但不会直接影响调用者 . 串行队列一次只能运行一个任务 . 如果其他任务已排队,则它们会按严格顺序等待并运行 .
并发队列可以允许多个任务同时运行,具体取决于可用的系统资源 .
使用本书中的新引用更新以回应编辑过的问题:
这仍然是完全错误的 . 部分参与:
这正是“同步执行”的意思 . 当您同步提交任务时,提交线程会等待代码完成持续 .
否 . 并发队列的重点是它们在开始后续任务之前等待一个正在运行的任务 . 这就是"concurrent"的意思 . 并发队列可以同时同时运行多个任务 .
不,这是错的 . 它完全取决于您使用什么函数将该块放在队列中 . 如果它使用
dispatch_sync()
,则等待队列执行该块 . 如果它使用dispatch_async()
,它不会等待;它马上就会继续 . 无论队列是串行还是并发,都是如此 .除主队列之外的任何队列,串行或并发可以运行在后台线程上提交给它的块 . 并且,如果你使用
dispatch_sync()
从主线程向并发队列提交一个块,那么's very possible that the block will execute on the main thread. That'因为GCD知道主线程在dispatch_sync()
调用内被阻塞,所以它也可以在那里运行块 .换句话说,队列的类型确实 not 指示块运行在哪个线程上 .
本书的作者根本不知道他/她在说什么 .
首先要了解,GCD你必须了解同步和异步执行之间的区别 .
Synchronous =在提交时执行并阻止它们提交的线程/队列 . 这意味着:
块(代码)仅在队列中转动时执行 .
块(代码)将阻塞执行队列,其他块(代码和同步)将等待 .
基本上,块将以FIFO格式执行 .
Asynchronous =无论队列/线程如何都立即开始执行,并且不阻塞队列/线程 . 即使队列上正在执行某些操作(同步和异步),也会执行 .
要了解错误的原因,我们将通过代码 .
第1-19行 - 定义的secondBlock
第23-43行 - 定义firstBlock
第47行 -
dispatch_async()
firstBlock(记住:异步执行)第41行[firstBlock]
dispatch_sync()
secondBlock(记住:同步执行)第43行[firstBlock] - firstBlock退出
第50行 - 线程休眠0.1秒
第52行 - 定义并执行第三个块(记住:异步执行) .
即使在队列上执行了secondBlock,第三块块也是异步执行并开始执行 . 为了实现块(代码)的排队,我们
dispatch_sync()
.注意
此函数相对于并发队列运行 . 这意味着
dispatch_sync()
将仅与当前队列同步 . 在其他线程(例如主线程)上,它似乎是异步的 .