iOS 多线程与线程安全(一)

iOS 中实现多线程的几种方式:

  dispatch 

  NSOperation

  performSelector

  NSThread

      pthread

 

一、dispatch,对pthread的封装

 

1. dispatch_sync  和 dispatch_aync

  dispatch_sync 程序会等待 dispatch_sync 同步执行完成之后才能继续往下走。

      dispatch_aync 程序讲任务添加到队列后继续往下执行,不必等待任务执行完成;一定不会开启新线程;以下代码会发生死锁:

// 例1:同步往当前串行队列添加任务,会产生死锁

- (void)viewDidLoad {

    [super viewDidLoad];

    dispatch_sync(dispatch_get_main_queue(), ^{

    });

}

 

  

2. 创建和获取队列。

    获取主队列:

dispatch_get_main_queue()

  获取后台队列:

//    第一个参数队列优先级,不同优先级获取到的queue不同
//    #define DISPATCH_QUEUE_PRIORITY_HIGH 2
//    #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
//    #define DISPATCH_QUEUE_PRIORITY_LOW (-2)
//    #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
//    第二个参数不为0时,获取不到queue
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

    创建串行队列:

dispatch_queue_t serialQueue = dispatch_queue_create("serial", NULL); 

    创建并发队列:    

dispatch_queue_t serialQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT); 

 

3. dispatch_group 等待被添加到group中的所有任务执行完毕,配合 dispatch_group_notify 或者 dispatch_group_wait。

    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("queue 2", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 10; i++) {
        dispatch_group_async(group, queue, ^{
            NSLog(@"任务 %ld", (long)i);
        });
    }
    dispatch_group_notify(group, queue, ^{
        NSLog(@"任务执行完毕");
    });

 

4. dispatch_after,延迟执行,一段时间后将指定的block到追加某队列中

    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);
    dispatch_after(time, dispatch_get_main_queue(),^{
        NSLog(@"3秒后");
    });

  

5、dispatch_barrier_async,dispatch_barrier_async函数会等待追加到 queue 上的任务全部执行结束之后,再将指定的任务追加到该并发队列中,并且该处理执行完毕之后queue才会恢复为一般动作。

以下代码的执行顺序:

// 第一部分,并发执行

// 第二部分,barrier block 2 执行

// 第二部分,barrier block 2 执行
// 第三部分 并发执行
    dispatch_queue_t queue = dispatch_queue_create("queue 2", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 10; i++) {
        dispatch_async(queue, ^{
            NSLog(@"任务 %ld", (long)i);   // 第一部分,并发执行
        });
    }
    
    // 第二部分,barrier block 1执行
    dispatch_barrier_sync(queue, ^{
        for (int i = 0; i < 10; i++) {
            NSLog(@"dispatch_barrier_sync %ld", (long)i); // 当前线程执行
        }
    });
    
    // 第二部分,barrier block 2 执行
    dispatch_barrier_async(queue, ^{
        for (int i = 0; i < 10; i++) {
            NSLog(@"dispatch_barrier_async %ld", (long)i); // 后台线程执行
        }
    });
    
    // 第三部分 并发执行
    for (int i = 10; i < 20; i++) {
        dispatch_async(queue, ^{
            NSLog(@"任务 %ld", (long)i);
        });
    }

 

6、dispatch_semaphore,信号量,通常用与线程同步,当信号量的值小于1时候,线程进入休眠状态等待,直到dispatch_semaphore信号量大于0

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    NSLog(@"1");
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        dispatch_semaphore_signal(semaphore);
        NSLog(@"2");
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    NSLog(@"3");

  输出顺序 1 2 3

 

7、dispatch_once 执行一次,通常用于实现单例

+ (instancetype)sharedInstance {
    static id sharedInstance;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        sharedInstance = [[[self class] alloc] init];
    });
    return sharedInstance;
}

  

 

二、NSOperation、NSOperationQueue,对NSthread的封装,更加面向对象,使用起来更加方便,可以设置任务优先级和依赖关系,控制最大执行数量    等。NSOperationQueue 在任务被添加后自动异步执行。

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue setMaxConcurrentOperationCount:5];
    for (int i = 0; i < 10; i++) {
        [queue addOperation:[NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"operation %ld, %@", (long)i, [NSThread currentThread]);
        }]];
    }
    
    NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op1 %@", [NSThread currentThread]);
    }];

    NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op2 %@",[NSThread currentThread]);
    }];
    NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op3 %@", [NSThread currentThread]);
    }];
    
    [op1 addDependency:op2];
    [op2 addDependency:op3];
    
    [queue addOperation:op2];
    [queue addOperation:op3];
    [queue addOperation:op1];

  

 

三、performSelectorInBackground、performSelectorOnMainThread

     NSObject封装的一系列多线程方法。

    [self performSelectorInBackground:@selector(operation) withObject:nil];
    [self performSelectorOnMainThread:@selector(operation) withObject:nil waitUntilDone:NO];
    [self performSelector:@selector(operation) onThread:[[NSThread alloc] init] withObject:nil waitUntilDone:NO];

  

 

四、NSThread 

    [[NSThread alloc] initWithBlock:^{
        NSLog(@"任务1");
    }];
    
    [[NSThread alloc] initWithTarget:self selector:@selector(operation) object:nil];

  

五、pthread(POSIX threads,简称Pthreads,是线程的POSIX标准,类Unix操作系统中均使用的操作系统线程)

void *pthreadExecute(void *data) {
    for (int i = 0; i < 100; i++) {
        NSLog(@"pthread 执行 %ld, %@", (long)i, [NSThread currentThread]);
        sleep(1);
    }
    return NULL;
}

- (void)pthread {
    pthread_t pth;
    pthread_create(&pth, NULL, pthreadExecute, NULL);

    sleep(10);
    pthread_cancel(pth);
    NSLog(@"pthread cancel %@", [NSThread currentThread]);
}

2020-06-08 16:16:36.523342+0800 多线程[6001:678321] pthread 执行 0, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:37.524526+0800 多线程[6001:678321] pthread 执行 1, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:38.525049+0800 多线程[6001:678321] pthread 执行 2, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:39.526688+0800 多线程[6001:678321] pthread 执行 3, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:40.527975+0800 多线程[6001:678321] pthread 执行 4, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:41.533475+0800 多线程[6001:678321] pthread 执行 5, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:42.539034+0800 多线程[6001:678321] pthread 执行 6, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:43.539568+0800 多线程[6001:678321] pthread 执行 7, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:44.542963+0800 多线程[6001:678321] pthread 执行 8, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:45.544117+0800 多线程[6001:678321] pthread 执行 9, <NSThread: 0x600002ccc340>{number = 6, name = (null)}
2020-06-08 16:16:46.524624+0800 多线程[6001:678116] pthread cancel <NSThread: 0x600002c8cd40>{number = 1, name = main}

  

posted @ 2020-06-08 15:35  一坨☁️  阅读(180)  评论(0编辑  收藏  举报