GCD线程同步

  • 根据使用场景设计代码

多线程下载多个图片,图片全部下载完成后,执行需要的任务

  • 方法一: dispatch_group_t
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*图片1 */ });
dispatch_group_async(group, queue, ^{ /*图片2 */ });
dispatch_group_async(group, queue, ^{ /*图片3 */ }); 
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 图片全部现在完毕,执行下面的代码
/*
需要执行的代码
*/

});

多线程下载多个图片,下载任务按指定顺序同步执行

  • 方法一:dispatch_group_enter、dispatch_group_level,dispatch_group_wait
  • dispatch_group_enter、dispatch_group_level成对出现dispatch_group_wait会收到同步信号
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    
    sleep(5);
    NSLog(@"图片1");
    dispatch_group_leave(group);
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    
    sleep(2);
    NSLog(@"图片2");
    dispatch_group_leave(group);
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    
    sleep(1);
    NSLog(@"图片3");
    dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
    
    NSLog(@"任务完成");
});
  • 方法二: dispatch_barrier(阻塞任务)

    /* 创建并发队列 */
    dispatch_queue_t concurrentQueue = dispatch_queue_create("test.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
    /* 添加两个并发操作A和B,即A和B会并发执行 */
    dispatch_async(concurrentQueue, ^(){
    NSLog(@"OperationA");
    });
    dispatch_async(concurrentQueue, ^(){
    NSLog(@"OperationB");
    });
    /* 添加barrier障碍操作,会等待前面的并发操作结束,并暂时阻塞后面的并发操作直到其完成 */
    dispatch_barrier_async(concurrentQueue, ^(){
    NSLog(@"OperationBarrier!");
    });
    /* 继续添加并发操作C和D,要等待barrier障碍操作结束才能开始 */
    dispatch_async(concurrentQueue, ^(){
    NSLog(@"OperationC");
    });
    dispatch_async(concurrentQueue, ^(){
    NSLog(@"OperationD");
    });
    
    
    2017-04-04 12:25:02.344 SingleView[12818:3694480] OperationB
    2017-04-04 12:25:02.344 SingleView[12818:3694482] OperationA
    2017-04-04 12:25:02.345 SingleView[12818:3694482] OperationBarrier!
    2017-04-04 12:25:02.345 SingleView[12818:3694482] OperationD
    2017-04-04 12:25:02.345 SingleView[12818:3694480] OperationC
    
  • 方法三:信号量机制(dispatch_semaphore)

  • 信号量机制主要是通过设置有限的资源数量来控制线程的最大并发数量以及阻塞线程实现线程同步等。

  • GCD中使用信号量需要用到三个函数:

    • dispatch_semaphore_create用来创建一个semaphore信号量并设置初始信号量的值;
    • dispatch_semaphore_signal发送一个信号让信号量增加1(对应PV操作的V操作);
    • dispatch_semaphore_wait等待信号使信号量减1(对应PV操作的P操作);
/* 创建一个信号量 */
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

/* 任务1 */
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
/* 耗时任务1 */
NSLog(@"任务1开始");
[NSThread sleepForTimeInterval:3];
NSLog(@"任务1结束");
/* 任务1结束,发送信号告诉任务2可以开始了 */
dispatch_semaphore_signal(semaphore);
});

/* 任务2 */
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
/* 等待任务1结束获得信号量, 无限等待 */
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
/* 如果获得信号量则开始任务2 */
NSLog(@"任务2开始");
[NSThread sleepForTimeInterval:3];
NSLog(@"任务2结束");
});
[NSThread sleepForTimeInterval:10];


2017-06-02 21:21:37.777156+0800 OC[6869:324518] 任务1开始
2017-06-02 21:21:40.782648+0800 OC[6869:324518] 任务1结束
2017-06-02 21:21:40.782829+0800 OC[6869:324519] 任务2开始
2017-06-02 21:21:43.788198+0800 OC[6869:324519] 任务2结束

你可能感兴趣的:(GCD线程同步)