GCD
1.串行队列
dispatch_queue_t queue = dispatch_queue_create("serial", NULL);
dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
创建串行队列的两种方式 (队列 FIFO 按添加的先后顺序执行)
2.并行队列
dispatch_queue_create("并发", DISPATCH-QUEUE-CONCURRENT)
3.主队列
dispatch_async(dispatch_get_main_queue(), ^{
})
同步 异步
同步 dispatch group sync
同步执行:比如这里的dispatch_sync,这个函数会把一个block加入到指定的队列中,而且会一直等到执行完blcok,这个函数才返回。因此在block执行完之前,调用dispatch-sync方法的线程是阻塞的。
int main(int argc, const char * argv[])
{
@autoreleasepool{
dispatch_sync(dispatch_get_main_queue(), ^(void) {
NSLog(@"这里死锁了");
});
}
return 0;
}
死锁问题
把dispatch-sync看做一个任务,主线程默认是串行队列。 dispatch-sync是同步线程,必须等block完成之后才能往下调用。在主线程 添加一个同步线程。然后把block添加到主线程队列的尾部。由于主线程是主线程,在添加sync这个同步线程的时候必须等这个同步线程执行完成之后才能往下进行操作,而sync必须要等block完成之后才能有返回值,所以主线程和block有相互等待产生死锁(都在同一个线程之内)
dispatch_queue_t queue = dispatch_queue_create("serial", nil); dispatch_sync(queue, ^(void) { NSLog(@"这个也不会死锁"); });
该方法就不会发生死锁
为什么说向另一个串行队列添加任务不一定导致死锁呢,因为队列是可以嵌套的,比如在A队列(串行)添加一个任务a,在a这个任务中向B队列(串行)添加任务b,在b这个任务中又向A队列添加任务,这就间接满足了“在某一个串行队列中,同步的向这个队列添加block”。但是我们好像每一次都没有直接向相同的队列中添加block。
我觉得是在同一个队列中添加串行线程才会发生死锁
--
异步 dispatch-group-async
--
异步执行:一般使用dispatch-async,这个函数也会把一个block加入到指定的队列中,但是和同步执行不同的是,这个函数把block加入队列后不等block的执行就立刻返回了。
Group
dispatch-group-t group = dispatch-group-create();
dispatch-group-enter(dispatch-group-t group); dispatch-group-leave(dispatch-group-t group);
dispatch_group-notify()
这三个成对出现 其实单纯的使用并不用使用enter 和 leave 这两个方法
例
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t testQueue= dispatch_queue_create("标志", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group,testQueue, ^{
NSLog(@"====1 ");
});
dispatch_group_async(group,testQueue, ^{
sleep(10);
NSLog(@"====2 ");
});
dispatch_group_async(group,testQueue, ^{
sleep(1);
NSLog(@"=====3");
});
dispatch_group_notify(group, testQueue, ^{
NSLog(@"多线程完成");
});
就不用使用该上述配对
如
dispatch_group_enter(group);
dispatch_group_async(group,testQueue, ^{
NSLog(@"====1 ");
dispatch_group_async(group,testQueue, ^{
sleep(10);
NSLog(@"====2 ");
dispatch_group_leave(group);
});
});
dispatch_group_enter(group);
dispatch_group_async(group,testQueue, ^{
sleep(1);
NSLog(@"=====3");
dispatch_group_leave(group);
});
dispatch_group_notify(group, testQueue, ^{
NSLog(@"多线程完成");
});
这种异步里面嵌套异步的方法要用 group-enter 和 group-leave配对才能使notify正确调用
dispatch_apply
dispatch apply函数是dispatch_sync函数和Dispatch Group的关联API,该函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等到全部的处理执行结束(简单来说就是类似循环调用 该线程是并发线程)
Dispatch Semaphore (信号量)
关键字
dispatch_semaphore_create(1);//创建1个信号
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//当计数值大于1时,或者在待机中计数 值大于1时,对该计数减1并且返回。
dispatch_semaphore_signal(semaphore);//对计数值加1
create(num)创建并发线程的个数 num控制并发个数
wait使信号量减一 signal加一使用方法
dispatch_async(quene, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 1");
sleep(1);
NSLog(@"complete task 1");
dispatch_semaphore_signal(semaphore);
});
这是一个表格
<table>
<tr>
<th width=10%, bgcolor=yellow >参数</th>
<th width=45%, bgcolor=yellow>同步</th>
<th width="45%", bgcolor=yellow>异步</th>
</tr>
<tr>
<td bgcolor=#eeeeee> 串行 </td>
<td> 不创建线程,顺序执行 FIFO </td>
<td> 创建一个新线程,顺序执行 </td>
</tr>
<tr>
<td bgcolor=#00FF00> 并行 </td>
<td> 不创建新线程,顺序执行</td>
<td> 创建多个新线程 并发执行 </td>
</tr>
<tr>
<td bgcolor=#00FF00> 主线程 </td>
<td> 死锁</td>
<td> 不创建新线程顺序执行 </td>
</tr>
</table>
网友评论