2021-08-04 多线程之多读单写

2021-08-04  本文已影响0人  我是小胡胡123

如何实现多读单写。
创建一个自定义并发队列。
读:同步并发 读
写:dispatch_barrier_sync 同步栅栏提交到并发队列。AFNetworking设置公共头部header用的此法。
有很多地方都说可以dispatch_barrier_async并发队列。 实际测试,这种方式会有问题。死锁。 个人理解是队列满了。

测试程序如下:


#import "testDispatchbarrier.h"

@implementation testDispatchbarrier{
    dispatch_queue_t queue;
    NSInteger aValue;
}

-(instancetype)init{
    self =[super init];
    //queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    queue = dispatch_queue_create("read_write", DISPATCH_QUEUE_CONCURRENT);
    return self;
}


/// 读者,读者 并发
/// 读者,写者互斥
/// 写者,写者互斥
/// readAvalue,可以在多个线程里面调用
- (NSInteger)readAvalue {
    __block NSInteger a;
    //同步读取
    dispatch_sync(self->queue, ^{ //用并发队列,可以在多个线程里面调用
        //sleep(5);
        a=self->aValue;
    });//用同步调用,无论是在哪个线程,立刻需要读取到结果,所以用同步提交
    return a;
}

///
///串行队列
///全局并发队列
///
///
- (void)write{
      //异步栅栏 调用,设置写
    //下面是AFNetworking的header设置的方法
    dispatch_barrier_sync(self->queue, ^{//写的时候,里面的任务要全部清理完(不管是读还是写,都要等他们执行完),然后只允许我一个人去写
    //dispatch_barrier_async(self->queue, ^{    //如果用dispatch_barrier_async 就会卡死,不能写。 我觉得是因为并发队列满了。
        self->aValue=self->aValue+1;
    }); //用sync等执行完返回,用并发队列,可以多个线程调用
}

-(void)test{
    testDispatchbarrier *a =[testDispatchbarrier new];
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t bingfaqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    for (int i=0; i<1000; i++) {
        dispatch_group_async(group, bingfaqueue, ^{
            NSLog(@"一大堆人读: %@", @([a readAvalue]));
        });
    }
    //1000次+1操作,如果有资源竞争问题,结果值会小于1000
    for (int i=0; i<1000; i++) {
        dispatch_group_async(group, bingfaqueue, ^{
            [a write];
        });
    }
    for (int i=0; i<1000; i++) {
        dispatch_group_async(group, bingfaqueue, ^{
            NSLog(@"一大堆人读: %@", @([a readAvalue]));
        });
    }

    //1
    dispatch_group_async(group, bingfaqueue, ^{
         
    });
    
    dispatch_group_async(group, bingfaqueue, ^{
         
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"全部都执行完了=%@",  @([a readAvalue]));
    });
    NSLog(@"开始测试");
}
@end



@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    UIButton*btn=[UIButton buttonWithType:UIButtonTypeSystem];
    [self.view addSubview:btn];
    btn.frame=CGRectMake(20, 100, 100, 50);
    btn.backgroundColor=[UIColor redColor];
    [btn setTitle:@"测试" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(testAction) forControlEvents:UIControlEventTouchUpInside];
}

-(void)testAction{
    [self test5];
}

-(void)test5{
    testDispatchbarrier *aa=[testDispatchbarrier new];
    [aa test];
}


@end
上一篇 下一篇

猜你喜欢

热点阅读