TLS: WebRTC中ThreadManager的线程局部存储

1. 什么是线程局部存储:

线程局部存储(TLS,Thread-Local Storage):

  1. 线程局部存储(TLS)允许每个线程保存一份独立的数据副本,避免多个线程共享数据导致的竞争问题。
    每个线程可以根据pthread_key_t 类型的 键 来 存储 和 访问 自己的私有数据。
  2. pthread_key_t:
    pthread_key_t 是在POSIX线程库(pthread)中用于实现TLS的一种类型。

2. 如何使用POXIS线程局部存储:

(1)创建键:

cpp 复制代码
int pthread_key_create(pthread_key_t *key, void (*destructor)
(void*));

创建一个线程局部存储键,并绑定到一个特定的数据释放函数(可选)

  • key: 用于存储创建的 pthread_key_t 键。
  • destructor: 当线程退出时,如果 TLS 中有数据与该键关联,destructor 函数将被调用来释放该数据(这个参数可以是 NULL,表示不需要清理函数)。

(2)设置线程局部存储值:

cpp 复制代码
int pthread_setspecific(pthread_key_t key, const void *value);
  • key: 用于存取数据的 pthread_key_t 键。
  • value: 要设置的线程局部存储的值。

(3)获取线程局部存储值:

cpp 复制代码
void *pthread_getspecific(pthread_key_t key);
  • key: 用于检索数据的 pthread_key_t 键。
  • 返回值:返回与 key 关联的线程局部存储数据,如果没有数据,则返回 NULL。

(4)销毁键:

cpp 复制代码
int pthread_key_delete(pthread_key_t key);

3. 线程局部存储与加锁的关系:

线程局部存储(TLS)只适用于每个线程有独立数据的场景,可以避免线程间的冲突,但不适用于共享数据的情况;

加锁用于共享资源的情况,保证共享数据的访问是互斥的。

所以二者解决的是不同的问题, 适用于不同的场景,线程局部存储不能完全替代加锁。

4. WebRTC中ThreadManager的线程局部存储类型:

cpp 复制代码
// src/rtc_base/thread.h
class ThreadManager
{
#if defined(WEBRTC_POSIX)
  pthread_key_t key_;
#endif
};

// src/rtc_base/thread.cc
ThreadManager::ThreadManager()
{
	pthread_key_create(&key_, nullptr);
}

Thread* ThreadManager::CurrentThread()
{
  	return static_cast<Thread*>(pthread_getspecific(key_));
}

void ThreadManager::SetCurrentThreadInternal(Thread* thread)
{
  	pthread_setspecific(key_, thread);
}

5. 线程局部存储的demo小程序:

"key_"可以理解为是一个"存储区",而不是一个"键",key_中存储所有的线程与线程私有数据间的映射。

demo:

c 复制代码
#include <pthread.h>
#include <stdio.h>

pthread_key_t key;

void destructor(void *value) {
    printf("Thread-specific data is being freed: %s\n", (char*)value);
}

void* thread_func_1(void* arg) {
    pthread_setspecific(key, "Thread-specific data 111");

    // Retrieve thread-specific data
    char* value = pthread_getspecific(key);
    printf("Thread-specific data 111: %s\n", value);

    return NULL;
}

void* thread_func_2(void* arg) {
    pthread_setspecific(key, "Thread-specific data 222");

    // Retrieve thread-specific data
    char* value = pthread_getspecific(key);

    printf("Thread-specific data 111: %s\n", value);

    return NULL;
}

int main() {
    pthread_t thread1, thread2;

    // Create a key with a destructor function
    pthread_key_create(&key, destructor);

    // Create threads
    pthread_create(&thread1, NULL, thread_func_1, NULL);
    pthread_create(&thread2, NULL, thread_func_2, NULL);

    // Wait for threads to finish
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    // Delete the key
    pthread_key_delete(key);

    return 0;
}
相关推荐
OpenLoong 开源社区6 天前
打破 NAT 限制,零侵入跨网络通信:基于 WebRTC 的透明 TCP 隧道跨网络通信方案
网络协议·tcp/ip·开源·webrtc·openloong开源社区
探鸽小钛9 天前
4G 终端 ES8311 - 挂断一次,下次说话就没声了之解决办法
物联网·音视频·嵌入式·esp32·webrtc
草根大哥10 天前
AI 编程实践之自建视频CDN
音视频·webrtc·低延迟直播·视频cdn·低延迟cdn
EasyCVR10 天前
应急指挥怕延迟?聊聊视频汇聚/视频融合/视频分析EasyCVR平台WebRTC低延迟方案
音视频·webrtc·easycvr
TrueDei11 天前
WebRTC ICE 候选变成 mDNS 地址导致连接失败:原因分析与解决方案
webrtc
中屹指纹浏览器svip14 天前
WebRTC泄露是什么,怎么关闭?
webrtc
海边捡石子15 天前
从零设计一个通用智能电话平台:FreeSWITCH + ESL + AI 实战架构
人工智能·架构·webrtc
音视频牛哥15 天前
不换摄像机,也能接入 WebRTC?SmartMediaKit RTSP/RTMP 转 WHIP 技术实践
音视频·webrtc·smartmediakit·rtsp转whip·rtmp转whip·whip推流·rtsp转webrtc播放
直播技术开发交流17 天前
Android 端 WHIP 协议推流技术实践:相机/录屏/多路转发WHIP实现测试
webrtc·android whip·rtsp转whip·毫秒级实时媒体流·whip低延时推送·whip推送实现·rtsp转webrtc
程序员阿明19 天前
docker搭建视频流服务go2rtc,webRTC
docker·容器·webrtc