// If the data being loaded is a video, return NO // Even better may be to implement this on the RCTImageURLLoader that would try to load it, // but we'd have to run the logic both in RCTPhotoLibraryImageLoader and // RCTAssetsLibraryRequestHandler. Once we drop iOS7 though, we'd drop // RCTAssetsLibraryRequestHandler and can move it there. staticNSRegularExpression *videoRegex = nil; if (!videoRegex) { NSError *error = nil; videoRegex = [NSRegularExpression regularExpressionWithPattern:@"(?:&|^)ext=MOV(?:&|$)" options:NSRegularExpressionCaseInsensitive error:&error]; if (error) { RCTLogError(@"%@", error); } }
for (id<RCTImageURLLoader> loader in _loaders) { // Don't use RCTImageURLLoader protocol for modules that already conform to // RCTURLRequestHandler as it's inefficient to decode an image and then // convert it back into data if (![loader conformsToProtocol:@protocol(RCTURLRequestHandler)] && [loader canLoadImageURL:requestURL]) { returnYES; } } returnNO; }
当多线程访问此方法时,线程 A 跑到 if (!videoRegex) { 这一句时,判断 videoRegex 为空,就进入方法块对它进行初始化。如果这时刚好发生线程切换,此时线程 B 也跑到这个 if 判断来,因为 videoRegex 还没初始化完成,所以其仍然是空,因此线程 B 也开始进入方法块,对之进行初始化。
这样问题就发生了 – 这个静态变量初始化了 2 次!
这会导致什么问题呢?如果线程 A 初始化完之后,进入下面的正则匹配,从 firstMatchInString 跑到 enumerateMatchesInString:options:range:usingBlock: 去遍历匹配字符串。但是这期间线程 B 将匹配器 (videoRegex) 重新初始化了!我们不希望发生的事情 (crash) 就这样发生了!