多线程

pthread

  • 一套通用的多线程API,适用于Unix/Linux/Windows等系统,跨平台/可移植
  • 使用难度大
  • 基于C语言
  • 程序员管理线程生命周期
  • 几乎不用

NSThread

  • 使用更加面向对象
  • 简单易用,可直接操作线程对象
  • 基于OC语言
  • 程序员管理线程生命周期
  • 偶尔使用

GCD

  • 旨在替代NSThread等线程技术
  • 充分利用设备的多核
  • 基于C语言
  • 自动管理线程生命周期
  • 经常使用
queue

队列:用来存放任务,将需要执行的任务添加到队列中,队列会遵循FIFO原则(先进先出、后进后出),将队列中的任务取出,放到对应的线程中执行

dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
# DISPATCH_QUEUE_SERIAL			串行队列
# DISPATCH_QUEUE_CONCURRENT		并行队列
dispatch_queue_t queue = dispatch_queue_create("队列标签", DISPATCH_QUEUE_SERIAL);
同步/异步

同步:立即执行任务
异步:延迟执行任务

dispatch_sync(queue, ^{

});
dispatch_async(queue, ^{

});
主队列同步任务:
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
    }
});
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
    }
});
NSLog(@"step 2 %@", [NSThread currentThread]);

线程死锁,应用崩溃

主队列异步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"async 1_%d %@", i, [NSThread currentThread]);
    }
});
dispatch_async(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"async 2_%d %@", i, [NSThread currentThread]);
    }
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 2_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
  • 异步任务被延后执行
  • 异步任务在主线程下执行
全局队列同步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
    }
});
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
    }
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
  • 同步任务被立即执行
  • 同步任务在主线程下执行
全局队列异步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"async 1_%d %@", i, [NSThread currentThread]);
    }
});
dispatch_async(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"async 2_%d %@", i, [NSThread currentThread]);
    }
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_0 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_0 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 2_1 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 1_1 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_2 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 1_2 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_3 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 1_3 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_4 <NSThread: 0x600002f4c600>{number = 8, name = (null)}
async 1_4 <NSThread: 0x600002f46800>{number = 7, name = (null)}
  • 异步任务被延后执行
  • 异步任务在多个新的线程下执行
串行队列同步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("serial_queue_label", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
    }
});
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
    }
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
  • 同步任务被立即执行
  • 同步任务在主线程下执行
串行队列异步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("serial_queue_label", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"async 1_%d %@", i, [NSThread currentThread]);
    }
});
dispatch_async(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"async 2_%d %@", i, [NSThread currentThread]);
    }
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_0 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 1_1 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 1_2 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 1_3 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 1_4 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_0 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_1 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_2 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_3 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_4 <NSThread: 0x600002f46800>{number = 7, name = (null)}
  • 异步任务被延后执行
  • 异步任务在一个新的线程下执行
并行队列同步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("concurrent_queue_label", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
    }
});
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
    }
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 1_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_0 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_3 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
sync 2_4 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
  • 同步任务被立即执行
  • 同步任务在主线程下执行
并行队列异步任务
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("concurrent_queue_label", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"async 1_%d %@", i, [NSThread currentThread]);
    }
});
dispatch_async(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"async 2_%d %@", i, [NSThread currentThread]);
    }
});
NSLog(@"step 2 %@", [NSThread currentThread]);
step 1 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
step 2 <NSThread: 0x600002f3a1c0>{number = 1, name = main}
async 1_0 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_0 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
async 1_1 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_1 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
async 1_2 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_2 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
async 1_3 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_3 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
async 1_4 <NSThread: 0x600002f46800>{number = 7, name = (null)}
async 2_4 <NSThread: 0x600002fb0c80>{number = 9, name = (null)}
  • 异步任务被延后执行
  • 异步任务在多个新的线程下执行

NSOperation

  • 底层是GCD
  • 比GCD多了一些更简单实用的功能
  • 使用更加面向对象
  • 基于OC语言
  • 自动管理线程生命周期
  • 经常使用

线程死锁

当前串行队列中,使用sync函数添加任务(立即执行任务),会卡住当前的串行队列(产生死锁)

dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"step 1 %@", [NSThread currentThread]);
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
    }
});
dispatch_sync(queue, ^{
    for (int i = 0; i < 5; ++i) {
        NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
    }
});
NSLog(@"step 2 %@", [NSThread currentThread]);
dispatch_queue_t queue = dispatch_queue_create("serial_queue_label", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
    NSLog(@"step 1 %@", [NSThread currentThread]);
    dispatch_sync(queue, ^{
        for (int i = 0; i < 5; ++i) {
            NSLog(@"sync 1_%d %@", i, [NSThread currentThread]);
        }
    });
    dispatch_sync(queue, ^{
        for (int i = 0; i < 5; ++i) {
            NSLog(@"sync 2_%d %@", i, [NSThread currentThread]);
        }
    });
    NSLog(@"step 2 %@", [NSThread currentThread]);
});

死锁的执行流程:

  1. 串行队列中的任务1在线程中执行
  2. 线程中的任务1在执行中需要立即(sync)执行串行队列中的任务2
  3. 串行队列中的任务2必须在线程中的任务1执行完毕后,才能进入线程中执行
  4. 线程中的任务1必须立即执行任务2,才能执行完毕
  5. 死锁

解锁方法:

  • 将任务分布到不同的队列中
  • 将串行队列改为并行队列
  • 将立即(sync)执行改为延迟(async)执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值