浅谈一种规避iOS多线程Crash的方案

一般来说,多线程编程因具有以下几个优点,一直被广泛应用:

  • 资源利用率更好
  • 程序设计在某些情况下更简单
  • 程序响应更快

但是因为多线程而导致的crash问题,也是令程序员非常头疼的一个问题,因为线程调度执行顺序的不确定性,造成了crash一般都是小概率出现,在开发测试阶段很难发现,而一旦上线面对用户,造成的影响却是不容小觑的。

一、Crash的场景

有一种特别常见的会造成crash的场景为:多线程读写可变数组/字典

我们来看几个简单的测试代码,看看到底在什么情况下会引起Crash:

// 1. 多线程只读数据
NSMutableDictionary * dict1 = [[NSMutableDictionary alloc] init];
[dict1 setObject:@"test0" forKey:@"test0"];
[dict1 setObject:@"test1" forKey:@"test1"];
[dict1 setObject:@"test2" forKey:@"test2"];
for (int i = 0; i < 1000; i++) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSString * key = [NSString stringWithFormat:@"test%d", i%3];
        NSString * value = dict1[key];
        NSLog(@"%@:%@", key, value);
    });
}
    
// 2. 多线程只写数据
// 字典仅有一个key
// 多线程写同一个key
NSMutableDictionary * dict2 = [[NSMutableDictionary alloc] init];
for (int i = 0; i < 1000; i++) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [dict2 setObject:@(i) forKey:@"test"];
    });
}

// 3. 多线程只写数据
// 字典有多个key
// 多线程同时写不同key
NSMutableDictionary * dict3 = [[NSMutableDictionary alloc] init];
for (int i = 0; i < 1000; i++) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [dict3 setObject:[NSString stringWithFormat:@"test%d", i] forKey:[NSString stringWithFormat:@"test%d", i]];
    });
}

// 4. 多线程只写数据
// 字典有多个key
// 多线程随机写key
NSMutableDictionary * dict4 = [[NSMutableDictionary alloc] init];
for (int i = 0; i < 1000; i++) {
    int x = arc4random() % 3;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [dict4 setObject:[NSString stringWithFormat:@"test%d", i] forKey:[NSString stringW

你可能感兴趣的:(iOS)