Tagged Pointer

先解决个问题

首先定义
@property (nonatomic, copy) NSString *test;
复制代码
方法一
for (int i = 0; i < 1000; i++) {
      dispatch_async(dispatch_get_global_queue(0, 0), ^{
          self.test = [NSString stringWithFormat:@"%@",@"123"];
      });
  }

复制代码
方法二
for (int i = 0; i < 1000; i++) {
      dispatch_async(dispatch_get_global_queue(0, 0), ^{
          self.test = [NSString stringWithFormat:@"%@",@"abababababababababababababab"];
      });
  }
复制代码

运行段代码 有什么区别? 现象是什么?安全

  • 方法一:正常运行
  • 方法二:崩溃

为何?

查看崩溃日志多线程

  • 坏内存访问

分析缘由

test属性 setter方法实际执行如下内容async

- (void)setTest:(NSString *)test {
    if (![_test isEqualToString:test]) {
        [_test release];
        _test = [test copy];
        [test release];
    }
}
复制代码

因为test 修饰为nonatomic 因此是线程不安全的。 当多条线程同时访问,形成屡次release ,因此坏内存访问。优化

解决方式

修饰改成atomic 或者加锁ui

疑问

为何方式一不会崩溃?

首先打印两个NSString的类型this

解决疑问

正常对象都是 指针指向对象的地址, 指针指向堆内存中的地址,因此方法二会由于多线程访问而形成坏内存访问,而TaggedPointer 则不会建立内存,而是在isa指针上作手脚。在指针上存放具体值。atom

TaggedPointer

64位开始 引入了Tagged Pointer 技术,用于优化NSNumber、NSDate、NSString 等小对象存储spa

打印方式1、方式二的NSString地址

从上图能够看出 0结尾的为对象地址 由于以16位为基准 内存对齐线程

而方法二的明显不同。指针

咱们看一下objc_release的源码
objc_release(id obj)
{
    if (!obj) return;
    if (obj->isTaggedPointer()) return;
    return obj->release();
}
复制代码

当obj为isTaggedPointer的时候 直接返回。 因此更加验证了刚才的说法 即:用指针存值,而不是在堆中生成对象

objc_object::isTaggedPointer() 
{
    return _objc_isTaggedPointer(this);
}
复制代码
# define _OBJC_TAG_MASK 1UL
static inline bool 
_objc_isTaggedPointer(const void * _Nullable ptr)
{
    return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}
复制代码
#if (TARGET_OS_OSX || TARGET_OS_IOSMAC) && __x86_64__ //若是是OSX && X86 
    // 64-bit Mac - tag bit is LSB
# define OBJC_MSB_TAGGED_POINTERS 0 
#else //其余状况 包含iOS
    // Everything else - tag bit is MSB
# define OBJC_MSB_TAGGED_POINTERS 1
#endif


#if OBJC_MSB_TAGGED_POINTERS
# define _OBJC_TAG_MASK (1UL<<63) //若是是OSX && X86 

#else
# define _OBJC_TAG_MASK 1UL //其余状况 包含iOS

#endif
复制代码

从上面能够看当在OSX && X86 出当1UL<<63为1的时候为TaggedPointer

从上面能够看当在iOS平台 出当尾数为1的时候为TaggedPointer

感兴趣的能够关注个人公众号。天天会更新哦 很是感谢。相互交流 提高技术~

相关文章
相关标签/搜索