您的位置:首页 > 其它

GCD之五:dispatch_barrier_async

2014-04-08 22:27 309 查看
在访问数据库或文件时,使用Serial Dispatch Queue可避免数据竞争的问题。

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

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

虽然利用Dispatch Group和dispatch_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 Queue和dispatch_barrier_basync函数可实现高效率的数据库访问和文件访问。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: