1、什么是gcd?
- 全称是Grand Central Dispatch;
- 纯C语言,提供了很多强大的函数;
- 是苹果公司为多核的并行运算提供的解决方案,会自动的利用更多的cpu内核,能自动管理线程的生命周期。
2、线程和队列的关系?
3、队列有几种?
- 队列分为串行队列
(FIFO)
和并发队列,主队列属于串行队列,全局队列属于并发队列。主队列在main函数之前就已经创建了。
4、iOS多线程的方案有哪些?
- iOS多线程方案分为四种:pthread,NSThread,GCD和NSOpreation。
- 其中pthread,NSThread,需要开发者手动管理线程的生命周期。
- NSOpreation是对GCD面向对象的封装,NSOpreation提供了添加线程的依赖关系,设置线程优先级,观察线程状态,暂停,继续,取消线程等方法,方便开发者使用,但效率方面不如GCD。
5、举例说明线程的死锁问题
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"1");
dispatch_sync(queue, ^{
NSLog(@"2");
});
NSLog(@"3");
});
- 解析:
DISPATCH_QUEUE_SERIAL
说明是串行队列,遵循FIFO
原则, dispatch_async
异步函数中有3个任务NSLog(@"1")
,dispatch_sync(queue, ^{})
,NSLog(@"3")
会首先加入到串行队列queue
中,且依次执行,但在执行dispatch_sync(queue, ^{})
时,因为这里是一个同步函数,要想代码块执行完毕,此时就必须执行NSLog(@"2")
,但NSLog(@"2")
也是加入到同一个队列queue
中的,且其排在NSLog(@"3")
打印之后,所以此时就会出现互相等待的现象,想要执行NSLog(@"3")
就必须执行完毕dispatch_sync(queue, ^{})
代码块,想要执行完代码块就必须执行完NSLog(@"2")
,想要执行完NSLog(@"2")
就必须执行完NSLog(@"3")
。
死锁逻辑
6、常用的GCD方法及使用环境
dispatch_sync(<#dispatch_queue_t _Nonnull queue#>, <#^(void)block#>)
dispatch_async(<#dispatch_queue_t _Nonnull queue#>, <#^(void)block#>)
- 信号量
dispatch_semaphore_t
- 当信号量为0的时候会堵塞线程,起到一种锁的效果
// 创建信号量 value可控制并发数量
dispatch_semaphore_create(<#intptr_t value#>)
// 信号量-1
dispatch_semaphore_wait(<#dispatch_semaphore_t _Nonnull dsema#>, <#dispatch_time_t timeout#>)
// 信号量 +1
dispatch_semaphore_signal(<#dispatch_semaphore_t _Nonnull dsema#>)
- 栅栏函数
dispatch_barrier_async
- 将函数两边的任务隔开,栅栏函数之前的任务执行完毕之后,才会执行栅栏函数之后的任务
dispatch_barrier_async(<#dispatch_queue_t _Nonnull queue#>, <#^(void)block#>)
// 创建线程组
dispatch_group_create()
// 线程组异步执行
dispatch_group_async(<#dispatch_group_t _Nonnull group#>, <#dispatch_queue_t _Nonnull queue#>, <#^(void)block#>)
// 线程组所有函数执行完毕之后将会调用该函数
dispatch_group_notify(<#dispatch_group_t _Nonnull group#>, <#dispatch_queue_t _Nonnull queue#>, <#^(void)block#>)
//进组和出组函数 成对出现 可使用这俩函数建立任务之间的依赖关系
dispatch_group_enter(<#dispatch_group_t _Nonnull group#>)
dispatch_group_leave(<#dispatch_group_t _Nonnull group#>)
- 延时函数
dispatch_after
- 可以用该函数做一些延时任务
dispatch_after(<#dispatch_time_t when#>, <#dispatch_queue_t _Nonnull queue#>, <#^(void)block#>)
- 一次执行函数
dispatch_once
- 代码块内的操作只会执行一次,常在创建单利的时候使用
dispatch_once(<#dispatch_once_t * _Nonnull predicate#>, <#^(void)block#>)
// 创建
dispatch_source_create(<#dispatch_source_type_t _Nonnull type#>, <#uintptr_t handle#>, <#uintptr_t mask#>, <#dispatch_queue_t _Nullable queue#>)
// 回调函数
dispatch_source_set_event_handler(<#dispatch_source_t _Nonnull source#>, <#^(void)handler#>)
网友评论