image.png
- 同步函数
dispatch_sync :
- 阻塞当前线程,直到当前添加到队列的任务执⾏完毕
- 只能在当前线程执⾏任务,不具备开启新线程的能⼒。
- 异步函数
dispatch_async:
- 不会阻塞当前线程,不需要等待,任务可以继续执⾏;
- 可以在新的线程执⾏任务,具备开启新线程的能⼒。(
并发队列可以开启多条⼦线程,串⾏队列只能开启⼀条⼦线程
)
同步异步
-
dispatch_sync() 在当前线程, 以同步的方式立刻执行任务
-
dispatch_async() 具备开起新线程的能力, 以异步的方式执行任务, 不会阻塞其他线程
队列类型
-
并发
队列 Concurrent
可以让多个任务并发(同时)执行 -
串行
队列 Serial
让任务一个接着一个的执行(一个任务执行完毕后, 才能执行下一个任务)
容易混淆的术语 同步 异步 并发 串行
-
同步和异步的主要区别: 是否能开启新的线程
同步: 在当前线程中执行任务, 不具备开启新线程的能力
异步: 在新的线程中执行任务, 具备开启新线程的能力 -
并发和串行主要影响: 任务执行的方式
并发: 多个任务并发(同时)执行
串行: 一个任务执行完毕后 再执行下一个任务
多线程面试题
- (void)interview1
{
// 以下代码, 会有什么问题
NSLog(@"任务1-%@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"任务2-%@", [NSThread currentThread]);
});
NSLog(@"任务3-%@", [NSThread currentThread]);
/*
首先任务1会打印
我们获取到一个主队列, 以同步的方式在主队列里添加了任务, sync会立刻在当前线程执行该任务, 因为是串行队列会阻塞当前线程
但是interview1这个任务也在主线程中执行, 任务2必须等待它执行完毕后才能执行, 但是interview1要执行完毕,
又要等到任务2执行完毕后,它才能继续执行,所以就产生了死锁, 解决方案是以async的方式添加,这样就会新开启一条线程执行任务2,
*/
}
- (void)interview2
{
NSLog(@"任务1-%@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"任务2-%@", [NSThread currentThread]);
});
NSLog(@"任务3-%@", [NSThread currentThread]);
/*
dispatch_async以异步方式执行任务, 因为是主队列,不会开启新的线程, 还是以串行的方式执行,
任务3不会阻塞当前线程
打印结果 任务1 任务3 任务2
*/
}
- (void)interview3
{
// 以下代码在主线程执行, 会不会产生死锁? 会
NSLog(@"任务1----%@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{ // block0
NSLog(@"任务2----%@", [NSThread currentThread]);
dispatch_sync(queue, ^{ //block1
NSLog(@"任务3----%@", [NSThread currentThread]);
});
NSLog(@"任务4----%@", [NSThread currentThread]);
});
NSLog(@"任务5----%@", [NSThread currentThread]);
/*
首先创建的是一条串行队列, 以异步的方式添加任务到队列中, 在以同步的方式添加任务到队列中,同步任务会立刻在当前线程执行任务,并阻塞当前线程
但是当前队列是串行队列, block0这个任务还未执行完毕, block1需要等到block0执行完毕后才能继续执行,
但是block0 又要等待block1执行完毕后 才能继续执行, 两个任务互相等待, 产生了死锁. 解决防范是block1 以async的方式执行任务,
*/
}
- (void)interview4
{
// 以下代码在主线程执行, 会不会产生死锁? 不会
NSLog(@"任务1----%@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"任务2----%@", [NSThread currentThread]);
// 虽然是同步执行,要求立刻执行,但是queue和queue2 并不是一个队列,所以不会互相等待,
dispatch_sync(queue2, ^{
NSLog(@"任务3----%@", [NSThread currentThread]);
});
NSLog(@"任务4----%@", [NSThread currentThread]);
});
NSLog(@"任务5----%@", [NSThread currentThread]);
/*
队列1是串行队列, 队列2是并发队列, 首先异步的方式添加任务2到串行队列中, 在以同步的方式添加任务3到并发队列中,会立刻执行
任务3虽然是以同步的方式添加到队列,但是queue1和queue2不在一个队列中, 不会产生互相等待的情况, 所以不会产生死锁
打印顺序是 任务1 -> 任务5 -> 任务2 -> 任务3 > 任务4
*/
}
- (void)interview5
{
// 以下代码在主线程执行, 会不会产生死锁? 不会
NSLog(@"任务1----%@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"任务2----%@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"任务3----%@", [NSThread currentThread]);
});
NSLog(@"任务4----%@", [NSThread currentThread]);
});
NSLog(@"任务5----%@", [NSThread currentThread]);
/*
创建的并发队列, 异步的方式添加任务2到队列中, 再已同步的方式添加任务3到队列中, 任务3会立刻执行
因为是并发队列, 可以多个任务同时执行, 不会阻塞队列
打印结果是 任务1 -> 任务5 -> 任务2 -> 任务3 -> 任务4
*/
}
网友评论