Tagged Pointer

一. Tagged Pointer應用場景

ViewController

@interface ViewController ()
@property (strong, nonatomic) NSString *name;
@end

以下2段代碼能發(fā)生什么事?有什么區(qū)別?

1. 片段1
 dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    for (int i = 0; i < 1000; i++) {
        dispatch_async(queue, ^{
            self.name = [NSString stringWithFormat:@"abcfdfdgfdgdffd"];
        });
    }
2. 片段2
 dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    for (int i = 0; i < 1000; i++) {
        dispatch_async(queue, ^{
            self.name = [NSString stringWithFormat:@"abc"];
        });
    }

結論:

  1. 片段1執(zhí)行會引起異常,片段2正常執(zhí)行。
  2. 片段1是并發(fā)給name屬性賦值,就是同時很多個線程訪問name的set方法,因為name是使用nonatomic修飾的,不是線程安全的,相當于同時訪問以下代碼,可能導致多次釋放name,所以會拋異常。
- (void)setName:(NSString *)name
{
    if (_name != name) {
        [_name release];
        _name = [name retain];
    }
}

解決方法:
a) 使用atomic修飾name屬性
b) 在dispatch_async里邊加鎖
c) 使用串行隊列

  1. 片段2是使用的Tagged Pointer技術,直接將數(shù)據(jù)存儲在指針當中,所以self.name根本不存在釋放堆空間內(nèi)存的操作,所以不會有問題。

二. Tagged Pointer介紹

image.png
  1. 從64bit開始,iOS引入了Tagged Pointer技術,用于優(yōu)化NSNumber、NSDate、NSString等小對象的存儲
  2. 在沒有使用Tagged Pointer之前, NSNumber等對象需要動態(tài)分配內(nèi)存、維護引用計數(shù)等,NSNumber指針存儲的是堆中NSNumber對象的地址值
  3. 使用Tagged Pointer之后,NSNumber指針里面存儲的數(shù)據(jù)變成了:Tag + Data,也就是將數(shù)據(jù)直接存儲在了指針中
  4. 當指針不夠存儲數(shù)據(jù)時,才會使用動態(tài)分配內(nèi)存的方式來存儲數(shù)據(jù)
  5. objc_msgSend能識別Tagged Pointer,比如NSNumber的intValue方法,直接從指針提取數(shù)據(jù),節(jié)省了以前的調(diào)用開銷
  6. 如何判斷一個指針是否為Tagged Pointer?
    a) iOS平臺,最高有效位是1(第64bit)
    b) Mac平臺,最低有效位是1
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

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