Objective-C Dispatch Queue API(2)

本文介绍了几个GCD函数。dispatch_barrier_async可用于高效数据库和文件访问,解决读写数据竞争问题;dispatch_sync在追加的Block执行完成前会一直等待,存在死锁情况;dispatch_apply按指定次数将Block追加到指定队列并等待处理结束;dispatch_suspend / dispatch_resume用于队列挂起和恢复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、dispatch_barrier_async

使用Concurrent Dispatch Queue 和 dispatch_barrier_async函数可以实现高效的数据库访问和文件访问。

test0:并行执行文件读任务。

-(blk)getTask:(int)x
{
    return ^{
        NSLog(@"非ui线程%d  -->%@",x,[NSThread currentThread]);
        [NSThread sleepForTimeInterval:1];
    };   
}
    blk blk1_read=[self getTask:1];
    blk blk2_read=[self getTask:2];
    blk blk3_read=[self getTask:3];
    blk blk4_read=[self getTask:4];
    blk blk5_read=[self getTask:5];

//    文件操作任务追加到可并行执行队列中
    dispatch_queue_t myConcurrentQueue=dispatch_queue_create("concurrentQueue",DISPATCH_QUEUE_CONCURRENT);
//    追加任务 
    dispatch_async(myConcurrentQueue, blk1_read);
    dispatch_async(myConcurrentQueue, blk2_read);
    dispatch_async(myConcurrentQueue, blk3_read);
    dispatch_async(myConcurrentQueue, blk4_read);
    dispatch_async(myConcurrentQueue, blk5_read);
//输出:任务并行执行。
2019-03-17 20:37:50.860566+0800 Block[43868:9860169] 非ui线程4  --><NSThread: 0x600000419540>{number = 5, name = (null)}
2019-03-17 20:37:50.860569+0800 Block[43868:9860166] 非ui线程2  --><NSThread: 0x6000004144c0>{number = 4, name = (null)}
2019-03-17 20:37:50.860573+0800 Block[43868:9860175] 非ui线程1  --><NSThread: 0x600000414600>{number = 3, name = (null)}
2019-03-17 20:37:50.860596+0800 Block[43868:9860167] 非ui线程3  --><NSThread: 0x600000419580>{number = 6, name = (null)}
2019-03-17 20:37:50.862177+0800 Block[43868:9860177] 非ui线程5  --><NSThread: 0x600000414cc0>{number = 7, name = (null)}

test1:在读取任务过程中增加文件写操作,会导致读取任务读取的数据与预期不一致、数据竞争。函数dispatch_barrier_async可以解决此问题;
举例:

//    新加写操作
    blk blk_write=[self getTask:6];
    省略...
    dispatch_async(myConcurrentQueue, blk3_read);
//    新加写操作
    dispatch_barrier_async(myConcurrentQueue, blk_write);
    dispatch_async(myConcurrentQueue, blk4_read);
//输出:
2019-03-17 20:46:50.277234+0800 Block[43949:9863969] 非ui线程2  --><NSThread: 0x600001ab5e40>{number = 4, name = (null)}
2019-03-17 20:46:50.277234+0800 Block[43949:9863967] 非ui线程1  --><NSThread: 0x600001ab6180>{number = 3, name = (null)}
2019-03-17 20:46:50.277234+0800 Block[43949:9863970] 非ui线程3  --><NSThread: 0x600001ab3900>{number = 5, name = (null)}
2019-03-17 20:46:51.281700+0800 Block[43949:9863967] 非ui线程6  --><NSThread: 0x600001ab6180>{number = 3, name = (null)}
2019-03-17 20:46:52.286637+0800 Block[43949:9863967] 非ui线程4  --><NSThread: 0x600001ab6180>{number = 3, name = (null)}
2019-03-17 20:46:52.286637+0800 Block[43949:9863969] 非ui线程5  --><NSThread: 0x600001ab5e40>{number = 4, name = (null)}
    

任务2开始: 2019-03-17 20:46:50
任务1开始: 2019-03-17 20:46:50
任务3开始: 2019-03-17 20:46:50
任务6开始: 2019-03-17 20:46:51
任务4开始: 2019-03-17 20:46:52
任务5开始: 2019-03-17 20:46:52

由输出可得出:
使用 dispatch_async追加任务到Concurrent Dispatch Queue并行执行;
dispatch_barrier_async会等待已经追加到Concurrent Dispatch Queue上的任务全部完成后再追加任务到该Concurrent Dispatch Queue中,然后由dispatch_barrier_async追加的任务执行完毕后,Concurrent Dispatch Queue才回复常规动作,后边追加的任务4和任务5 继续并行执行。

1.可以保证没有读操作进行时,开始执行写操作,且之心写操作时其他追加任务
等待。直到写操作完成后继续并行执行度任务。
2.通过 dispatch_barrier_async依次追加多个任务到同个Concurrent Dispatch Queue中,此时执行模式类似向一个Serial Dispatch Queue追加多个任务,任务会以FIFO、且等待的方式依次执行。

2、dispatch_sync

在追加的Block执行完成之前,dispatch_sync一直等待。

    dispatch_queue_t gdp=dispatch_get_global_queue(0, 0);
    NSLog(@"a");
    dispatch_sync(gdp, ^{
        NSLog(@"sfawefawf");
        [NSThread sleepForTimeInterval:2];
    });
    NSLog(@"b");
//等待2秒继续执行当前线程
2019-03-17 21:59:28.374185+0800 Block[44578:9891478] a
2019-03-17 21:59:28.374364+0800 Block[44578:9891478] sfawefawf
2019-03-17 21:59:30.375489+0800 Block[44578:9891478] b

死锁情况:
Main Dispatch Queue和Serial Dispatch Queue


//1 在主线程中执行
   dispatch_queue_t mq = dispatch_get_main_queue();
    dispatch_sync(mq, ^{
        NSLog(@"hello");
    });
 //2
    dispatch_queue_t mq = dispatch_get_main_queue();
    dispatch_async(mq, ^{
        dispatch_sync(mq, ^{
            NSLog(@"hello");
        });

    });
 //3
  dispatch_queue_t  mq=dispatch_queue_create("mySerialDispatchQueue",NULL);
  dispatch_async(mq,^{
      dispatch_sync(mq,^{
      NSLog(@"Hello");
     };});
  });




3、dispatch_apply

dispatch_apply按指定的次数将Block追加到指定的Dispatch Queue中去。
dispatch_apply函数会等待全部处理结束才返回。

  dispatch_queue_t queue=dispatch_get_global_queue(0, 0);
    dispatch_apply(5, queue, ^(size_t index) {
        NSLog(@"%zu",index);
    });
 //输出:
2019-03-17 22:17:34.789618+0800 Block[44764:9899583] 0
2019-03-17 22:17:34.789626+0800 Block[44764:9899616] 1
2019-03-17 22:17:34.789727+0800 Block[44764:9899583] 2
2019-03-17 22:17:34.789727+0800 Block[44764:9899616] 3
2019-03-17 22:17:34.789751+0800 Block[44764:9899614] 4
2019-03-17 22:17:34.789875+0800 Block[44764:9899583] done

//demo:

    dispatch_queue_t queue=dispatch_get_global_queue(0, 0);
    NSArray *arrary=@[@"1",@"2",@"3",@"4"];
    NSLog(@"--%@",[NSThread currentThread]);
    dispatch_async(queue, ^{
       NSLog(@"--%@",[NSThread currentThread]);
        dispatch_apply([arrary count], queue, ^(size_t index) {
            NSLog(@"%@----%@",[arrary objectAtIndex:index],[NSThread currentThread]);
        });
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"update ui");
        });
    });
    //输出:
2019-03-17 22:37:06.171917+0800 Block[45007:9908566] --<NSThread: 0x60000108e9c0>{number = 1, name = main}
2019-03-17 22:37:06.172254+0800 Block[45007:9908609] --<NSThread: 0x6000010da580>{number = 3, name = (null)}
2019-03-17 22:37:06.172421+0800 Block[45007:9908609] 1----<NSThread: 0x6000010da580>{number = 3, name = (null)}
2019-03-17 22:37:06.172573+0800 Block[45007:9908609] 2----<NSThread: 0x6000010da580>{number = 3, name = (null)}
2019-03-17 22:37:06.172706+0800 Block[45007:9908609] 3----<NSThread: 0x6000010da580>{number = 3, name = (null)}
2019-03-17 22:37:06.172839+0800 Block[45007:9908609] 4----<NSThread: 0x6000010da580>{number = 3, name = (null)}
2019-03-17 22:37:06.177690+0800 Block[45007:9908566] update ui

4、dispatch_suspend / dispatch_resume

队列挂起和恢复
dispatch_suspend(queue);
dispatch_resume(queue);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值