偶现问题复现 ,for 循环10万次增加偶现概率
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t concurrentQueue = dispatch_queue_create("tianyao", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
for(int i = 0;i < 100000;i++){
[self writeTest];
NSLog(@"%d 线程:%@", i, [NSThread currentThread]);
}
});
// dispatch_queue_t concurrentQueue2 = dispatch_queue_create("tianyao2", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
for(int i = 0;i < 100000;i++){
[self readTest];
NSLog(@"%d 线程:%@", i, [NSThread currentThread]);
}
});
}
- (void)writeTest{
DYTestManager *manager = [DYTestManager shareInstant];
NSArray *arr = @[@"1",@"2",@"3",@"4",@"5"];
NSMutableArray *arrM = [NSMutableArray arrayWithArray:arr];
[arrM addObject:@(random())];
manager.dayRankList = arrM;
NSLog(@"写入的数组%@",arrM);
}
- (void)readTest{
DYTestManager *manager = [DYTestManager shareInstant];
NSArray *arr = manager.dayRankList;
NSLog(@"读出的数组");
}
尝试5次, 每次分别给予10万次读和写 , 出现4次crash
问题复现
dayrankList变量存在同时写入的情况, 这个情况是极低的概率出现, 所以会出现偶现的crash
问题修复
//
// ViewController.m
// writeread
//
// Created by wanggang on 2021/3/9.
//
#import "ViewController.h"
#import "DYTestManager.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t concurrentQueue = dispatch_queue_create("tianyao", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
for(int i = 0;i < 100000;i++){
[self writeTest];
NSLog(@"%d 线程:%@", i, [NSThread currentThread]);
}
});
// dispatch_queue_t concurrentQueue2 = dispatch_queue_create("tianyao2", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
for(int i = 0;i < 100000;i++){
[self readTest];
NSLog(@"%d 线程:%@", i, [NSThread currentThread]);
}
});
}
- (void)writeTest{
DYTestManager *manager = [DYTestManager shareInstant];
NSArray *arr = @[@"1",@"2",@"3",@"4",@"5"];
NSMutableArray *arrM = [NSMutableArray arrayWithArray:arr];
[arrM addObject:@(random())];
// 写操作
dispatch_queue_t queue = manager.readWriteQueue;
dispatch_barrier_async(queue, ^{
// Write action.
manager.dayRankList = arrM;
NSLog(@"内部写 线程:%@", [NSThread currentThread]);
});
NSLog(@"写入的数组%@",arrM);
}
- (void)readTest{
DYTestManager *manager = [DYTestManager shareInstant];
// 继续执行读操作
dispatch_queue_t queue = manager.readWriteQueue;
dispatch_sync(queue, ^{
// Read action3.
NSArray *arr = manager.dayRankList;
NSLog(@"内部读 线程:%@", [NSThread currentThread]);
});
}
@end
读写不同线程不会crash
image.png问题总结
- 同时读写都在一个线程 同步不会crash
- 读写在不同的线程, 偶现的crash , 非必现 ,demo验证10万分之1左右
- 读写在不同的线程通过增加锁验证可以解决
增加锁的主要代码如下:
// 创建一个并行队列
dispatch_queue_t queue = dispatch_queue_create("LLDebugtool.com", DISPATCH_QUEUE_CONCURRENT);
// 执行一些读操作
dispatch_sync(queue, ^{
// Read action1.
});
dispatch_sync(queue, ^{
// Read action2.
});
...
// 写操作
dispatch_barrier_async(queue, ^{
// Write action.
});
// 继续执行读操作
dispatch_sync(queue, ^{
// Read action3.
});
dispatch_sync(queue, ^{
// Read action4.
});
线程加读写锁之后的特点
- 同一时间,只能有一个线程进行写的操作。
- 同一时间,允许有多个线程进行读的操作。
- 同一时间,不允许既有写的操作,又有读的操作。
网友评论