GCD之五:dispatch_barrier_async

    在访问数据库或文件时,使用Serial Dispatch Queue可避免数据竞争的问题。

    写入处理确实不可与其他的写入处理以及包含读取处理的其他某些处理并行执行。但是如果读取处理只是读取处理并行执行,那么多个并行执行就不会发生问题。

    也就是说,为了高效率地进行访问,读取处理追加到Concurrent Dispatch Queue中,写入处理在任一个读取处理没有执行的状态下,追加到Serial Dispatch Queue即可(在写入处理结束之前,读取处理不可执行)。

    虽然利用Dispatch Groupdispatch_set_target_queue函数也可实现,但是源代码会很复杂。

    GCD为我们提供了更为聪明的解决方法——dispatch_barrier_async函数。该函数同dispatch_queue_create函数生成的Concurrent Dispatch Queue一起使用。

    首先dispatch_queue_create函数生成Concurrent Dispatch Queue,在dispatch_async中追加读取处理。

dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.ForBarrier", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, block0_for_reading);
dispatch_async(queue, block1_for_reading);
dispatch_async(queue, block2_for_reading);
dispatch_async(queue, block3_for_reading);
dispatch_async(queue, block4_for_reading);
dispatch_async(queue, block5_for_reading);
dispatch_async(queue, block6_for_reading);
dispatch_async(queue, block7_for_reading);

dispatch_release(queue);

     在block3_for_reading处理和block4_for_reading处理之间执行写入处理,并将写入的内容读取block4_for_reading处理以及之后的处理中。

dispatch_async(queue, block0_for_reading);
dispatch_async(queue, block1_for_reading);
dispatch_async(queue, block2_for_reading);
dispatch_async(queue, block3_for_reading);

/*
 * 写入处理
 *
 * 将写入的内容读取之后的处理中
 */
dispatch_async(queue, block4_for_reading);
dispatch_async(queue, block5_for_reading);
dispatch_async(queue, block6_for_reading);
dispatch_async(queue, block7_for_reading); 

    如果像下面这样简单地在dispatch_async中加入写入处理,那么根据Concurrent Dispatch Queue的性质,就有可能在追加到写入处理前面的处理中读取到与期待不符的数据,还可能因非法访问导致应用程序异常结束。如果追加多个写入处理,则可能发生更多问题,比如数据竞争等。

dispatch_async(queue, block0_for_reading);
dispatch_async(queue, block1_for_reading);
dispatch_async(queue, block2_for_reading);
dispatch_async(queue, block3_for_reading);
dispatch_async(queue, block_for_writing);
dispatch_async(queue, block4_for_reading);
dispatch_async(queue, block5_for_reading);
dispatch_async(queue, block6_for_reading);
dispatch_async(queue, block7_for_reading);

    因此我们要使用dispatch_barrier_async函数。Dispatch_barrier_async函数会等待追加到Concurrent Dispatch Queue上的并行执行的处理全部结束之后,再将指定的处理追加到该Concurrent Dispatch Queue中。然后在由dispatch_barrier_async函数追加到处理执行完毕后,Concurrent Dispatch Queue才恢复为一般的动作,追加到该Concurrent Dispatch Queue的处理又开始并行执行。

dispatch_async(queue, block0_for_reading);
dispatch_async(queue, block1_for_reading);
dispatch_async(queue, block2_for_reading);
dispatch_async(queue, block3_for_reading);
dispatch_barrier_async(queue, block_for_writing);
dispatch_async(queue, block4_for_reading);
dispatch_async(queue, block5_for_reading);
dispatch_async(queue, block6_for_reading);
dispatch_async(queue, block7_for_reading);

    如上所示,使用方法非常简单。公使用dispatch_barrier_async函数代替dispatch_async函数即可。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值