iOS tagged pointer

作者: 孙掌门 | 来源:发表于2020-02-22 16:55 被阅读0次

    iOS tagged pointer

    从 64bit 开始,苹果引入了 tagged pointer 计数,用于优化 NSNumber , NSDate , NSString 等小对象的存储,没有这个数据之前,NSNumber 等对象需要动态分配内存,维护引用计数,NSNumber 指针存储的是堆中NSNumber对象的地址值,而引入了这个计数之后,NSNumber 指针里面存储的数据是 : tag + data ,也就是直接将数据存储在指针中。这样做特别节省空间。如果这个数据特别大,指针存储不下这个数,那么会回复之前的方式,存储在堆区,然后指针存放堆区的地址。

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0 );
        for (int i = 0 ; i < 10000; i ++) {
            dispatch_async(queue, ^{
                self.name = [NSString stringWithFormat:@"%@",@"123sdfasfdas"];
            });
        }
    
    

    上面会发生什么呢?答案是可能崩溃,因为我们是多线程同时方位name的set方法,那么的set方法好比

    
    -(void)setName:(NSString *)name{
        if (_name != name) {
            [_name release];
            _name = [name copy];
        }
    }
    
    

    好比这样,多个线程有可能同时去 release,所以会崩溃

    解决方案,可以加锁,在name设置前后去加锁。

    如果改成这样呢?

    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0 );
        for (int i = 0 ; i < 10000; i ++) {
            dispatch_async(queue, ^{
                self.name = [NSString stringWithFormat:@"%@",@"123"];
            });
        }
        
    
    

    就是把一个长字符串变成一个短的字符创,这时候发现,没有崩溃。因为后一个指针为 tagged pointer 类型的,就不存在release的操作,值直接就存储再来指针的里面,直接取值就可以了,所以就不会崩溃,他就不是一个OC对象。

    
     NSString *str = [NSString stringWithFormat:@"123"];
        NSString *str1 = [NSString stringWithFormat:@"aefasfasdfasfdasf"];
        NSLog(@"%@  %@",[str class],[str1 class]);
    
    
    

    我们来打印下两个类

    
     NSTaggedPointerString  __NSCFString
    
    

    可以看到 第一个类为 tagged pointer 类,也证明了我们的猜想。

    其实源码里面是有判断的,当为mac 的时候 &1,当为ios的时候&(1<<63),所以 ios 最高有效位为1就为 tagged pointer 类型,mac 最低有效位为1就为tagged pointer

    相关文章

      网友评论

        本文标题:iOS tagged pointer

        本文链接:https://www.haomeiwen.com/subject/sunlqhtx.html