[TOC]
Barrier
: n. (用来禁止通行的各种)障碍物(如: 栅栏和关卡)
在看GCD的barrier
如何使用前,我们先了解barrier的英文意思.
barrier的用法非常简单,这里我就不过多赘述,且看下面的代码:
- (void)barrier
{
dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.for", DISPATCH_QUEUE_CONCURRENT);
NSMutableArray *arr = @[].mutableCopy;
[arr addObject:@(1)];
dispatch_async(queue, ^{
NSLog(@"bl1 arr: %@", arr);
});
dispatch_async(queue, ^{
NSLog(@"bl2 arr: %@", arr);
});
dispatch_async(queue, ^{
[arr addObject:@(0)];
[NSThread sleepForTimeInterval:2.0];
[arr addObject:@(7)];
NSLog(@"finished: %@", arr);
});
dispatch_async(queue, ^{
NSLog(@"bl4 arr: %@", arr);
});
dispatch_async(queue, ^{
NSLog(@"bl5 arr: %@", arr);
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2.5];
NSLog(@"bl6 arr: %@", arr);
});
}
/*
输出:
2016-12-29 17:53:10.681 GCD-Barrier[33828:1500632] bl2 arr: (
1
)
2016-12-29 17:53:10.681 GCD-Barrier[33828:1500627] bl1 arr: (
1
)
2016-12-29 17:53:10.681 GCD-Barrier[33828:1500646] bl4 arr: (
1,
0
)
2016-12-29 17:53:10.681 GCD-Barrier[33828:1500632] bl5 arr: (
1,
0
)
2016-12-29 17:53:12.754 GCD-Barrier[33828:1500647] finished: (
1,
0,
7
)
2016-12-29 17:53:13.229 GCD-Barrier[33828:1500654] bl6 arr: (
1,
0,
7
)
*/
上面这段代码模拟了一个异步读写操作. bl1
和bl2
读取到的结果都是1
,而bl4
和bl5
读取到的结果是1,0
,我在bl2
和bl4
之间插入了一个写入操作,第一个是一个没有延迟的写入操作,然后模拟了延迟2.5秒的一个写入操作,插入了一个7,结果是只有加了延迟的bl6的读取操作是正确的.
为什么这样说,因为在同一时间,不同的用户进行了不同的操作,比如评论,当我看别人的评论的时候,恰巧有个人刚提交了一个评论,提交评论时,需要执行一个插入操作,但是这时我读取到的评论列表没有那个人刚刚提交的评论,这样有可能会造成某种误会.
所以我们需要用些手段,当有写入操作的时候,不能让别的线程来进行读取,等写入完毕后,再允许别的线程读取.
GCD很方便的为我们提供了这种功能,且看下面这段代码:
- (void)barrier
{
dispatch_queue_t queue = dispatch_queue_create("com.example.gcd.for", DISPATCH_QUEUE_CONCURRENT);
NSMutableArray *arr = @[].mutableCopy;
[arr addObject:@(1)];
dispatch_async(queue, ^{
NSLog(@"bl1 arr: %@", arr);
});
dispatch_async(queue, ^{
NSLog(@"bl2 arr: %@", arr);
});
dispatch_barrier_async(queue, ^{
[arr addObject:@(0)];
[NSThread sleepForTimeInterval:2.0];
[arr addObject:@(7)];
NSLog(@"finished: %@", arr);
});
dispatch_async(queue, ^{
NSLog(@"bl4 arr: %@", arr);
});
dispatch_async(queue, ^{
NSLog(@"bl5 arr: %@", arr);
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2.5];
NSLog(@"bl6 arr: %@", arr);
});
}
/**
输出结果:
2016-12-30 09:40:01.353 GCD-Barrier[35219:1890287] bl1 arr: (
1
)
2016-12-30 09:40:01.353 GCD-Barrier[35219:1890761] bl2 arr: (
1
)
2016-12-30 09:40:03.385 GCD-Barrier[35219:1890761] finished: (
1,
0,
7
)
2016-12-30 09:40:03.385 GCD-Barrier[35219:1890287] bl5 arr: (
1,
0,
7
)
2016-12-30 09:40:03.385 GCD-Barrier[35219:1890761] bl4 arr: (
1,
0,
7
)
2016-12-30 09:40:05.924 GCD-Barrier[35219:1890762] bl6 arr: (
1,
0,
7
)
*/
上面的代码,我们使用了dispatch_barrier_async
这个方法,这个方法里面的任务执行的时候,会挂起当前队列里其他的任务,当这个方法里的任务执行完成之后,别的任务再继续执行.如下图:
嗯..就酱.
联系方式: 958246321