如何实现多读单写。
创建一个自定义并发队列。
读:同步并发 读
写: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
网友评论