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);