美文网首页GCDiOS开发之多线程
【多线程】dispatch_barrier_sync 和disp

【多线程】dispatch_barrier_sync 和disp

作者: BeethOven | 来源:发表于2021-12-09 15:34 被阅读0次
image.png
共同点和区别

共同点:分割queue中的任务任务执行

区别: 是否影响主线程代码的执行

  • dispatch_barrier_async
 NSLog(@"start");
 dispatch_queue_t quque = dispatch_queue_create("name", DISPATCH_QUEUE_CONCURRENT);
 dispatch_async(quque, ^{
 NSLog(@"1");
 });
 dispatch_async(quque, ^{
 NSLog(@"2");
 });
 dispatch_barrier_async(quque, ^{
 NSLog(@"dispatch_barrier_sync");
 });
 dispatch_async(quque, ^{
 NSLog(@"3");
 });
 dispatch_async(quque, ^{
 NSLog(@"4");
 });
 NSLog(@"end");

2021-12-09 10:42:13.613007+0800 TestOC[2093:1349166] start

2021-12-09 10:42:13.613193+0800 TestOC[2093:1349166] end

2021-12-09 10:42:13.613208+0800 TestOC[2093:1349326] 1

2021-12-09 10:42:13.613223+0800 TestOC[2093:1349327] 2

2021-12-09 10:42:13.613434+0800 TestOC[2093:1349326] dispatch_barrier_sync

2021-12-09 10:42:13.613559+0800 TestOC[2093:1349326] 3

2021-12-09 10:42:13.613568+0800 TestOC[2093:1349327] 4

  • dispatch_barrier_sync
NSLog(@"start");
 dispatch_queue_t quque = dispatch_queue_create("name", DISPATCH_QUEUE_CONCURRENT);
 dispatch_async(quque, ^{
 NSLog(@"1");
 });
 dispatch_async(quque, ^{
 NSLog(@"2");
 });
 dispatch_barrier_sync(quque, ^{
 NSLog(@"dispatch_barrier_sync");
 });
 dispatch_async(quque, ^{
 NSLog(@"3");
 });
 dispatch_async(quque, ^{
 NSLog(@"4");
 });
 NSLog(@"end");

start
2021-12-09 10:43:14.680469+0800 TestOC[2122:1350990] 1
2021-12-09 10:43:14.680495+0800 TestOC[2122:1350986] 2
2021-12-09 10:43:14.680703+0800 TestOC[2122:1350823] dispatch_barrier_sync
2021-12-09 10:43:14.680835+0800 TestOC[2122:1350823] end
2021-12-09 10:43:14.680849+0800 TestOC[2122:1350986] 3
2021-12-09 10:43:14.680853+0800 TestOC[2122:1350990] 4

结论:dispatch_barrier_sync会阻塞主线程任务的执行

注: 栅栏函数用用自定义的并发队列才有意义

  1. 尽量使用自定义的并发队列:
    使用全局队列起不到栅栏函数的作用
    使用全局队列时由于对全局队列造成堵塞,可能致使系统其他调用全局队列的地方也堵塞从而导致崩溃(并不是只有你在使用这个队列)
  1. 栅栏函数只能控制同一并发队列:打个比方,平时在使用AFNetworking做网络请求时为什么不能用栅栏函数起到同步锁堵塞的效果,因为AFNetworking内部有自己的队列
实现读写锁(多读单写)

@interface ViewController ()

@property (nonatomic, strong) dispatch_queue_t rwqueue;

@property (nonatomic, assign) NSInteger tickets;

@end

@implementation ViewController

 //初始化 异步队列
 self.rwqueue = dispatch_queue_create("rw.thread", DISPATCH_QUEUE_CONCURRENT);
 dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
 for (NSInteger i = 0; i < 30; i ++) {
 dispatch_async(queue, ^{
 [self readBarryier];
 [self readBarryier];
 [self writeBarrier];
 [self readBarryier];
 });
 }
}

- (void)readBarryier{
//添加任务到rwqueue
 dispatch_async(self.rwqueue, ^{
 NSLog(@"读文件 %@ - %ld",[NSThread currentThread], self.tickets);
 sleep(1);
 });
}
- (void)writeBarrier{
//barrier_async添加任务到self.rwqueue中
 dispatch_barrier_async(self.rwqueue, ^{
 self.tickets++;
 NSLog(@"写入文件 %@ - %ld",[NSThread currentThread], self.tickets);
 sleep(1);
 });
}
@end 
- (id)readDataForKey:(NSString*)key {
 __block id result;
 dispatch_sync(_concurrentQueue, ^{
 result = [self valueForKey:key];
 });
 return result;
}

- (void)writeData:(id)data forKey:(NSString*)key {
 dispatch_barrier_async(_concurrentQueue, ^{
 [self setValue:data forKey:key];
 });
}
  • 读:并发异步
    获取到值后返回给读者
    • 若使用并发异步则会先返回空的result 0x0,再通过getter方法获取到值
  • 写:写的那个时间段,不能有任何读者+其他写者
    • dispatch_barrier_async满足:等队列中前面的读写任务都执行完了再来执行当前任务

参考文章

相关文章

网友评论

    本文标题:【多线程】dispatch_barrier_sync 和disp

    本文链接:https://www.haomeiwen.com/subject/uppffrtx.html