objc的很多设计,从底层实现上都不完全是线程安全的,这也导致在一些极端的并发情况下,会引起竞争导致的内存访问错误问题。之前分析过_weak的设计不是多线程安全的,最近又踩坑了_block,发现这个居然也不是线程安全。
当然这也不是说 _block, _weak 这些不要用了,而是说在比较频繁创建释放且有多线程使用的情况下,不要用 ___block, _weak修饰,因为他们的确不是线程安全的。
关于__weak的问题原文 不安全的weak
一、问题
最近线上新版本发布后,由于框架大改版导致一个以前几乎没有暴露出来的crash突然暴露出来了,虽然总量和频率也不高,但是每天也能有几十次,这个crash还有很有特色的。
crash堆栈如下:
Exception Type: SIGTRAP
Exception Codes: 0 at 0x000000019cfb6e8c
Crashed Thread: 11
Thread 11 Crashed:
0 libsystem_blocks.dylib 0x000000019cfb6e8c _Block_object_dispose + 284
1 mttlite 0x0000000104bbe114 -[MttSpaceClearManager extractSimilarImages:inOperation:] (MttSpaceClearManager.mm:611)
2 mttlite 0x0000000104bbcc04 -[MttSpaceClearManager getSimilarImagesWithDataSource:inOperation:] (MttSpaceClearManager.mm:0)
3 mttlite 0x0000000104bbc6e0 __66-[MttSpaceClearManager getSimilarImagesWithDataSource:completion:]_block_invoke (MttSpaceClearManager.mm:0)
4 Foundation 0x000000019dfae82c ___NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 16
+ 16
5 Foundation 0x000000019deb6a28 -[NSBlockOperation main] + 72
6 Foundation 0x000000019deb5efc -[__NSOperationInternal _start:] + 740
7 Foundation 0x000000019dfb0700 ___NSOQSchedule_f + 272
8 libdispatch.dylib 0x000000019cf596c8 __dispatch_call_block_and_release + 24
9 libdispatch.dylib 0x000000019cf5a484 __dispatch_client_callout + 16
10 libdispatch.dylib 0x000000019cf30e14 __dispatch_continuation_pop$VARIANT$armv81 + 404
11 libdispatch.dylib 0x000000019cf304f8 __dispatch_async_redirect_invoke + 592
12 libdispatch.dylib 0x000000019cf3cafc