代码为主,为了方便加深自己记忆,且主要一GCD为主,因为最为常用
CGD
队列
串行队列
// 串行队列
dispatch_queue_t queueSync = dispatch_queue_create("queueSync", DISPATCH_QUEUE_SERIAL);
// 项目中提供的主队列就是串行队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
并行队列
// 并行队列
dispatch_queue_t queueAsync = dispatch_queue_create("queueAsync", DISPATCH_QUEUE_CONCURRENT);
// 系统提供的 globe 队列 为 并行队列
dispatch_queue_t globeQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
任务
同步任务
不会创建新线程
dispatch_sync(mainQueue, ^{});
异步任务
根据使用队列类型,决定是否创建新新线程
dispatch_async(mainQueue, ^{});
组合
同步任务 + 并行队列
// 1. 同步任务 + 并行队列 = 单线程+顺序执行
dispatch_sync(queueAsync, ^{
[Thread sleep];
NSLog(@"1---%@", [NSThread currentThread]);
});
dispatch_sync(queueAsync, ^{
[Thread sleep];
NSLog(@"2---%@", [NSThread currentThread]);
});
dispatch_sync(queueAsync, ^{
[Thread sleep];
NSLog(@"3---%@", [NSThread currentThread]);
});
异步任务 + 并行队列
dispatch_async(queueAsync, ^{
[Thread sleep];
NSLog(@"1---%@", [NSThread currentThread]);
});
dispatch_async(queueAsync, ^{
[Thread sleep];
NSLog(@"2---%@", [NSThread currentThread]);
});
dispatch_async(queueAsync, ^{
[Thread sleep];
NSLog(@"3---%@", [NSThread currentThread]);
});
同步任务 + 串行队列
dispatch_sync(queueSync, ^{
[Thread sleep];
NSLog(@"1---%@", [NSThread currentThread]);
});
dispatch_sync(queueSync, ^{
[Thread sleep];
NSLog(@"2---%@", [NSThread currentThread]);
});
dispatch_sync(queueSync, ^{
[Thread sleep];
NSLog(@"3---%@", [NSThread currentThread]);
});
异步任务 + 串行队列
dispatch_async(queueSync, ^{
[Thread sleep];
NSLog(@"1---%@", [NSThread currentThread]);
});
dispatch_async(queueSync, ^{
[Thread sleep];
NSLog(@"2---%@", [NSThread currentThread]);
});
dispatch_async(queueSync, ^{
[Thread sleep];
NSLog(@"3---%@", [NSThread currentThread]);
});
结论
根据上述代码打印的结果,我们可以得出:
区别 | 并行队列 | 串行队列 |
---|---|---|
同步(sync) | 没有开启新线程,串行执行任务 | 没有开启新线程,串行执行任务 |
异步(async) | 有开启新线程,并发执行任务 | 有开启新线程(1条),串行执行任务 |
死锁
在当前线程中,往当前线程所在串行队列中添加同步任务出现。知道原因就很好避免了,最常见的错误:
// 在主线程中,想主线程所在的主队列添加同步任务。
dispatch_sync(dispatch_get_main_queue(), ^{
[Thread sleep];
[Thread getCurrentThread:@"1"];
});
// 或者在其他线程中,向该线程所在队列串行队列中添加同步任务。其实和主线程死锁一个意思。
dispatch_async(queueSync, ^{
dispatch_sync(queueSync, ^{
[Thread sleep];
[Thread getCurrentThread:@"1"];
});
});
信号量
异步任务变同步
//7.1 异步线程强制修改成同步,asych 中的 name 变成,变更在 外层 Log 之前
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block NSString *name = @"Lee";
dispatch_async(queueAsync, ^{
[Thread sleep];
name = @"Tom";
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"semaphore end,name = %@", name);
数据安全
多线程对同一块数据进行操作,需要线程安全
// 7.2 线程加锁。
// 多线程异步操作同一块数据源,对数据源进行加锁操作,方式数据源混乱
dispatch_queue_t queueOne = dispatch_queue_create("one", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queueTwo = dispatch_queue_create("two", DISPATCH_QUEUE_SERIAL);
semaphoreOne = dispatch_semaphore_create(1);
countDown = 20;
__weak typeof(self) weakSelf = self;
dispatch_async(queueOne, ^{
[weakSelf numberCountDown];
});
dispatch_async(queueTwo, ^{
[weakSelf numberCountDown];
});
- (void)numberCountDown {
while (1) {
// 加信号量目的是为了 控制 当前对数据的操作结束后,才能进行下一项。
dispatch_semaphore_wait(semaphoreOne, DISPATCH_TIME_FOREVER);
if (countDown > 0) {
countDown--;
NSLog(@"%@", [NSString stringWithFormat:@"countDown:%d currentThread:%@", countDown, [NSThread currentThread]]);
[Thread sleep];
} else {
NSLog(@" count down == 0");
dispatch_semaphore_signal(semaphoreOne);
break;
}
dispatch_semaphore_signal(semaphoreOne);
}
}