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. 注意事项:
  • 内存管理
  • 线程安全
  • 性能优化
  • 清理时机
相关推荐
程序员编程指南9 分钟前
Qt 移动应用常见问题与解决方案
c语言·开发语言·c++·qt
kebeiovo23 分钟前
C++代码题部分(1)
开发语言·c++
tomato0933 分钟前
河南萌新联赛2025第(二)场:河南农业大学(补题)
开发语言·c++
双力臂4041 小时前
Java注解与反射:从自定义注解到框架设计原理
java·开发语言
潇凝子潇1 小时前
面条式代码(Spaghetti Code)
java·开发语言·log4j
码界奇点1 小时前
Python深度挖掘:openpyxl与pandas高效数据处理实战指南
开发语言·数据库·python·自动化·pandas·python3.11
lzhdim1 小时前
C#开发的Panel里控件拖放例子 - 开源研究系列文章
开发语言·开源·c#
Billy_Zuo2 小时前
Android调用python库和方法的实现
android·开发语言·python
EndingCoder2 小时前
Three.js 与 WebXR:初识 VR/AR 开发
开发语言·前端·javascript·ar·vr
liulilittle2 小时前
备忘录设计模式 vs 版本设计模式
开发语言·c++·算法·设计模式