從一道網(wǎng)易面試題淺談OC線程安全(轉(zhuǎn))

下面代碼會發(fā)生什么問題?
@property (nonatomic, strong) NSString *target;

dispatch_queue_t queue = dispatch_queue_create("parallel", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 1000000 ; i++) {
dispatch_async(queue, ^{
self.target = [NSString stringWithFormat:@"ksddkjalkjd%d",i];
});
}

當時我把自定義的隊列看成了串行隊列,然后回答:“沒錯呀”。后來一運行崩潰了……
面試后,我就仔細回想,敲了Demo,看看崩潰原因是啥。
正好試試小伙伴給我介紹的調(diào)試野指針的方法,XCode7以上才有的Address Sanitizer。
打開后發(fā)現(xiàn)是經(jīng)典的EXC_BAD_ACCESS錯誤,以我淺薄的經(jīng)驗來看,這種一般是對一個已釋放的內(nèi)存的對象再次發(fā)送消息出現(xiàn)的。


1503650160314466.jpg

再看看崩潰堆棧

噢,看來是對已釋放的對象再次發(fā)送了release信息。
我又留意到,這個對象是Strong修飾的。
那么他的Setter方法在MRC上就相當于

  • (void)setTarget:(NSString *)target { [target retain];//先保留新值 [_target release];//再釋放舊值 _target = target;//再進行賦值}
    那么什么時候會導致過多調(diào)用release呢,因為這是個并行隊列+異步。
    那么假如隊列A執(zhí)行到步奏2,還沒到步驟3時,隊列B也執(zhí)行到步驟2,那么這個對象就會被過度釋放,導致向已釋放內(nèi)存對象發(fā)送消息而崩潰。
    后來我想怎么可以修改這段代碼變?yōu)椴槐罎⒌哪兀?br> 1.使用串行隊列
    將set方法改成在串行隊列中執(zhí)行就行,這樣即使異步,但所有block操作追加在隊列最后依次執(zhí)行。
    2. 使用atomic
    atomic關鍵字相當于在setter方法加鎖,這樣每次執(zhí)行setter都是線程安全的,但這只是單獨針對setter方法而言的狹義的線程安全。
    3.使用weak關鍵字
    weak的setter沒有保留新值或者保留舊值的操作,所以不會引發(fā)重復釋放。當然這個時候要看具體情況能否使用weak,可能值并不是所需要的值。
    4.使用Tagged Pointer
    Tagged Pointer是蘋果在64位系統(tǒng)引入的內(nèi)存技術。簡單來說就是對于NSString(內(nèi)存小于60位的字符串)或NSNumber(小于2^31),64位的指針有8個字節(jié),完全可以直接用這個空間來直接表示值,這樣的話其實會將NSString和NSNumber對象由一個指針轉(zhuǎn)換成一個值類型,而值類型的setter和getter又是原子的,從而線程安全。
    比如上述代碼的字符串改短一些,就不會崩潰了。
    從而我們可以總結(jié)到,線程安全有以下幾種方法:
    單線程串行訪問

訪問加鎖

使用不進行額外操作的關鍵字(weak)

使用值類型

然而這只是保證了基本的線程安全(不崩潰),若是需要保證訪問出符合預期的數(shù)據(jù),則需要采用GCD的barrier或者自己在合適的時機加鎖。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • ———————————————回答好下面的足夠了---------------------------------...
    恒愛DE問候閱讀 1,846評論 0 4
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,658評論 30 472
  • 史上最全的iOS面試題及答案 iOS面試小貼士———————————————回答好下面的足夠了----------...
    Style_偉閱讀 2,580評論 0 35
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理。運行時機制的原理和運用場景。SDWebImage的原...
    LZM輪回閱讀 2,132評論 0 12
  • 生活就像海邊的海礁石與海水撞擊過無數(shù)次,雖然疼痛卻還是義無反顧。 我身邊有很多人,形形色色的人,但又因為我的性格 ...
    瘋姑娘阿閱讀 253評論 2 2

友情鏈接更多精彩內(nèi)容