我正在阅读一本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阻止其他线路
GCDExamples [2459:554259] 2阻止其他THREAD
GCDExamples [2459:554256] 3阻止其他线路
GCDExamples [2459:554256] 3阻止其他THREAD
GCDExamples [2459:554259] 2阻止其他THREAD // Point firs t
GCDExamples [2459:554256] 3阻止其他THREAD
关于输出的一些要点:“ 3 block other THREAD ”和“2 block other THREAD ”中显示的输出是该输出行的第一次出现
我的问题: 根据概念,因为dispatch_sync函数一旦第二个块启动它应该使队列等待而不是允许“第三个块”启动。但是如前面的输出所示,“2 block other THREAD”在“// Point first”之后的“3 block other THREAD”语句中显示。这表明dispatch_sync函数没有使队列等待。怎么可能?如果需要的话,请问我另外的其他信息。
编辑1:我在这里放置这本着名书籍的文字来解释我的观点。这本书是“iOS 7编程食谱”。文字如下: - “对于任何不涉及UI的任务,您可以在GCD中使用全局并发队列。这些允许同步或异步执行。但同步执行并不意味着您的程序在继续之前等待代码完成。它简单地说,并发队列将等到你的任务完成后再继续到队列中的下一个代码块。当你将一个块对象放在一个并发队列上时,你自己的程序总是会立即继续,而不必等待队列到执行代码。这是因为并发队列,顾名思义,在主线程以外的线程上运行代码。“
正如粗体文本所说,并发队列将等待UNTIL我的任务完成后再继续下一个块。我的块打印“2 block other THREAD”应该允许在“3 block other THREAD”开始之前完成,但不是这样的情况我的“2 block other THREAD”再次打印与“3 block other THREAD”语句混合时事实上我的所有“2挡其他线程”应该被允许完成然后“3挡其他线程”应该跟随。评论是否需要更多信息。
答案 0 :(得分:3)
&#34; dispatch_sync函数阻止提交块的并发队列,即使队列等待&#34;
如果这是书的内容,请将其扔掉。那是对的。
同步与异步是关于调用者。当某些代码调用dispatch_sync()
时,代码无法继续,直到调度的任务完成为止。队列未被阻止或被迫等待或等等。
相反,当代码调用dispatch_async()
时,任务被放入队列,调用者继续进行下一步。它不会等待调度的任务开始,更不用说完成了。
这是队列是并发还是串行的完全独立的问题。这种区别属于队列和它们运行的任务,但不会直接影响调用者。串行队列一次只能运行一个任务。如果其他任务已排队,则它们会严格按顺序运行。
并发队列可以允许多个任务同时运行,具体取决于可用的系统资源。
使用本书中的新引号更新以回应编辑过的问题:
对于不涉及UI的任何任务,您可以在GCD中使用全局并发队列。这些允许同步或异步执行。但同步执行并不意味着您的程序在继续之前等待代码完成。它只是意味着并发队列将等到任务完成后再继续到队列中的下一个代码块。当您将块对象放在并发队列上时,您自己的程序将始终立即继续,而无需等待队列执行代码。这是因为并发队列,顾名思义,在主线程以外的线程上运行代码。
这仍然是完全错误的。分开来看:
但是同步执行并不意味着程序在继续之前等待代码完成。
这正是&#34;同步执行&#34;的意思是。当您同步提交任务时,提交线程会在继续之前等待代码完成。
它只是意味着并发队列将等到任务完成后再继续到队列中的下一个代码块。
没有。并发队列的重点是,他们不等待一个正在运行的任务,然后再开始后续任务。这是&#34;并发&#34;手段。并发队列可以同时同时运行多个任务。
当您将块对象放在并发队列上时,您自己的程序会立即继续,而不必等待队列执行代码。
不,这是错的。它完全取决于您使用什么函数将该块放在队列中。如果它使用dispatch_sync()
,则它等待队列执行块。如果它使用dispatch_async()
,它就不会等待;它马上就会继续。无论队列是串行还是并发,都是如此。
这是因为并发队列,顾名思义,在主线程以外的线程上运行代码。
除主队列之外的任何队列,串行或并发可以运行在后台线程上提交给它的块。并且,如果您使用dispatch_sync()
从主线程向并发队列提交块,则该块很可能会在主线程上执行。这是因为GCD知道主线程没有做任何其他事情,因为它在dispatch_sync()
调用内被阻止了,所以它也可以在那里运行阻塞。
换句话说,队列的类型不指示块运行在哪个线程上。
本书的作者根本不知道他/她在说什么。
答案 1 :(得分:0)
首先要了解,GCD必须了解同步和异步执行之间的区别。
Synchronous =在提交时执行并阻止他们提交的线程/队列。这意味着:
基本上,这些块将以FIFO格式执行。
Asynchronous =无论队列/线程如何都立即开始执行,并且不阻塞队列/线程。即使队列中正在执行某些事务(同步和异步),也要执行。
要了解错误的原因,我们将完成代码。
dispatch_async()
firstBlock(记住:异步执行)dispatch_sync()
secondBlock(记住:同步执行)第三个块正在异步执行并开始执行,即使队列上正在执行secondBlock。为了实现块(代码)的排队,我们dispatch_sync()
。
此函数相对于并发队列运行。这意味着dispatch_sync()
将仅与当前队列同步。在其他线程(例如主线程)上,它似乎是异步的。