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. 注意事项:
  • 内存管理
  • 线程安全
  • 性能优化
  • 清理时机
相关推荐
m0_748708051 分钟前
C++中的观察者模式实战
开发语言·c++·算法
qq_5375626714 分钟前
跨语言调用C++接口
开发语言·c++·算法
wjs202424 分钟前
DOM CDATA
开发语言
Tingjct26 分钟前
【初阶数据结构-二叉树】
c语言·开发语言·数据结构·算法
猷咪1 小时前
C++基础
开发语言·c++
IT·小灰灰1 小时前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧1 小时前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q1 小时前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳01 小时前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾1 小时前
php 对接deepseek
android·开发语言·php