iOS中并发导致的Data Race问题

首先看一段代码

@interface ViewController ()

@property (nonatomic,strong)NSObject *obj;

@end

@implementation KVOViewController

- (void)viewDidLoad {
 for (NSUInteger i =0 ; i <10000; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self set]
            if (i == 9999) {
                NSLog(@"执行完成");
            }
        });
    }
}

@end

这段代码在执行过程中会出现EXC_BAD_ACCESS类型的crash,很多人都知道这个由于在多个线程中操作同一个数据区引起不安全的问题。

根本原因在于在属性obj的赋值不是原子性,我们知道在ARC机制下,对属性的赋值等价于MRC的如下代码:

- (void)setObj:(NSObject *)obj{
 if (_obj) {
        [_obj release];
        _obj = nil;
    }
    _obj = [obj retain];
    }
    

由于不是原子性,导致两个线程同时进入到setObj:方法,有可能对_obj变量同时释放两次。这种类型的问题用Xcode的 Thread Sanitizer线程检查工具检查出来,Xcode称这类问题为Data Race.

使用Xcode 的Thread Sanitizer工具详见:Thread Sanitizer and Static Analysis

上述只是一个极端例子,其实平时开发中,我们往往会忽略代码中隐藏的Data Race问题,特别是某个公共库的方法可能被多次调用时,下面是比较常见的例子:


typedef void (^GlobalBlock) (NSMutableDictionary *dic);

+ (void)setConfigType:(GlobalBlock) newParamsBlock  {
    
    static GlobalBlock block = nil;
    static BOOL isInitilized = NO;
    if (isInitilized) {
        isInitilized = YES;
        block = newParamsBlock;
    }
}

例如以上方法是一个类方法,该方法隐含定义了两个静态变量,由于静态变量的生命周期是整个APP运行期间。如果该方法在多个线程中被同时调用,则可能引发Data Race问题。

上述问题可以通过加锁的方式解决,如下:

+ (void)setConfigType:(GlobalBlock) newParamsBlock  {
    
    static GlobalBlock block = nil;
    static BOOL isInitilized = NO;
     @synchronized(self){
       if (isInitilized) {
          isInitilized = YES;
          block = newParamsBlock;
      }
     }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • __block和__weak修饰符的区别其实是挺明显的:1.__block不管是ARC还是MRC模式下都可以使用,...
    LZM轮回阅读 3,374评论 0 6
  • Xcode 8诞生有段时日了,不知道大家对其中的新Feature是否都学习过一遍了,今天给大家介绍下Xcode 8...
    MrPeak阅读 2,217评论 3 42
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,503评论 1 15
  • 2016,我似乎还没准备好迎接它,就已经到了say goodbye 的时候了! 人到了一定的年龄,越是觉得自己不够...
    樺浩阅读 169评论 0 1
  • 嗨,你好,我是日记星球第六期252号星宝宝,这是我的第40篇原创日记。我相信坚持的力量! 今天是个好...
    于艾湘阅读 839评论 2 2