iOS - TLS(线程本地存储)

从源码中,详细总结 TLS (Thread Local Storage) 的实现:

1. TLS 基本结构

objectivec 复制代码
// TLS 的基本结构
struct tls_data {
    pthread_key_t key;           // 线程本地存储的键
    void (*destructor)(void *);  // 清理函数
};

// 自动释放池的 TLS
class AutoreleasePoolPage {
    static pthread_key_t const key = AUTORELEASE_POOL_KEY;  // TLS key
    static pthread_key_t key;                               // 实际的 key
};

2. TLS 初始化

objectivec 复制代码
void tls_init(void) {
    // 1. 创建线程键
    _objc_pthread_key = pthread_key_create(&_objc_pthread_destroyspecific);
    
    // 2. 初始化主线程的 TLS
    pthread_setspecific(_objc_pthread_key, &_objc_main_thread);
    
    // 3. 初始化自动释放池的 key
    AutoreleasePoolPage::key = tls_create(&_objc_autoreleasepool_deallocate);
}

3. TLS 操作函数

objectivec 复制代码
// 1. 创建 TLS key
static pthread_key_t tls_create(void (*destructor)(void*)) {
    pthread_key_t key;
    int result = pthread_key_create(&key, destructor);
    if (result != 0) {
        _objc_fatal("pthread_key_create failed (%d)", result);
    }
    return key;
}

// 2. 获取 TLS 值
static inline void *tls_get(pthread_key_t key) {
    return pthread_getspecific(key);
}

// 3. 设置 TLS 值
static inline void tls_set(pthread_key_t key, void *value) {
    pthread_setspecific(key, value);
}

4. TLS 清理机制

objectivec 复制代码
// TLS 数据清理
static void tls_dealloc(void *p) {
    // 1. 检查占位符
    if (p == (void*)EMPTY_POOL_PLACEHOLDER) {
        return;
    }
    
    // 2. 清理自动释放池页面
    AutoreleasePoolPage *page = (AutoreleasePoolPage *)p;
    
    // 3. 验证页面完整性
    if (page->child) {
        _objc_fatal("thread-local storage corrupted");
    }
    
    if (page->parent) {
        _objc_fatal("thread-local storage corrupted");
    }
    
    // 4. 销毁页面
    page->kill();
}

5. TLS 在自动释放池中的应用

objectivec 复制代码
class AutoreleasePoolPage {
    // 1. 获取当前线程的热页面
    static inline AutoreleasePoolPage *hotPage() {
        AutoreleasePoolPage *result = (AutoreleasePoolPage *)
            tls_get_direct(key);
        if (result) result->fastcheck();
        return result;
    }
    
    // 2. 设置热页面
    static inline void setHotPage(AutoreleasePoolPage *page) {
        if (page) page->fastcheck();
        tls_set_direct(key, (void *)page);
    }
};

6. TLS 性能优化

objectivec 复制代码
// 1. 直接访问优化
static inline void *tls_get_direct(pthread_key_t key) {
    // 直接从线程本地存储获取数据
    return _pthread_getspecific_direct(key);
}

// 2. 快速检查
void fastcheck() {
#if FASTAUTORELEASEPOOL_SPIN_DEBUG
    // 仅在调试模式下执行完整检查
    check(false);
#else
    // 生产环境只做基本检查
    if (!magic) _objc_fatal("bad magic");
#endif
}

7. TLS 线程安全

objectivec 复制代码
// 1. 线程安全的访问
void *getSpecific() {
    // pthread_getspecific 是线程安全的
    return pthread_getspecific(key);
}

// 2. 线程检查
void check(bool die) {
    // 确保在正确的线程上操作
    if (thread != pthread_self()) {
        if (die) _objc_fatal("thread mismatch");
    }
}

8. TLS 使用场景

objectivec 复制代码
// 1. 自动释放池管理
static inline void *autoreleaseFast(id obj) {
    AutoreleasePoolPage *page = hotPage();
    if (page && !page->full()) {
        return page->add(obj);
    }
    return autoreleaseFullPage(obj);
}

// 2. 线程特定数据
static void setThreadSpecific(id value) {
    tls_set(_objc_pthread_key, value);
}

总结要点:

  1. 基本特性:
  • 线程私有存储
  • 键值对管理
  • 自动清理机制
  1. 性能考虑:
  • 直接访问优化
  • 快速路径
  • 内存效率
  1. 安全性:
  • 线程隔离
  • 数据保护
  • 完整性检查
  1. 应用场景:
  • 自动释放池
  • 线程本地缓存
  • 线程特定数据
  1. 注意事项:
  • 内存管理
  • 线程安全
  • 性能优化
  • 清理时机
相关推荐
Ai 编码助手37 分钟前
Go语言的数据竞争 (Data Race) 和 竞态条件 (Race Condition)
开发语言·后端·golang
cd小白1 小时前
Linux第二课:LinuxC高级 学习记录day04
linux·开发语言·学习
Batac_蝠猫2 小时前
iOS - Objective-C 底层实现中的哈希表
ios·散列表·xcode
Batac_蝠猫2 小时前
iOS - Objective-C 底层中的内存屏障
ios·objective-c·xcode
_可乐无糖2 小时前
跨平台实践:python中如何检查当前操作系统
android·python·ui·ios·appium·自动化
Techlifehacks2 小时前
[完整指南]如何轻松备份锁定/禁用的iPhone?
ios·cocoa·iphone
Techlifehacks2 小时前
如果 iPhone 丢失或被盗,如何远程擦除 iPhone?
ios·iphone
Batac_蝠猫2 小时前
iOS - block
macos·ios·cocoa
xiaoxiongniunai2 小时前
IOS工程师
科技·ios·objective-c
daily_23332 小时前
c++领域展开第十二幕——类和对象(STL简介——简单了解STL)超详细!!!!
开发语言·c++