iOS 多线程的理解

代码为主,为了方便加深自己记忆,且主要一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);
    }
}

你可能感兴趣的:(iOS 多线程的理解)