跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C 语言线程局部存储
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C语言线程局部存储 = 线程局部存储(Thread Local Storage, TLS)是C语言中一种允许每个线程拥有自己独立变量副本的机制。在多线程编程中,全局变量和静态变量默认是被所有线程共享的,而使用TLS可以创建线程私有的数据,避免竞争条件并简化线程同步。 == 基本概念 == 在C11标准之前,TLS通过编译器扩展(如GCC的<code>__thread</code>或MSVC的<code>__declspec(thread)</code>)实现。C11标准正式引入了<code>_Thread_local</code>关键字(可用宏<code>thread_local</code>替代)来支持线程局部存储。 线程局部存储的变量: * 每个线程拥有独立的副本 * 生命周期与线程相同 * 初始化仅在首次访问时进行(对于静态存储期变量) == 语法与声明 == 声明线程局部变量的语法如下: <syntaxhighlight lang="c"> #include <threads.h> thread_local int tls_var; // 文件作用域的TLS变量 void func() { static thread_local int static_tls; // 静态存储期的TLS变量 thread_local int local_tls; // 错误:不能声明自动存储期的TLS变量 } </syntaxhighlight> == 代码示例 == 以下示例展示TLS变量的基本用法: <syntaxhighlight lang="c"> #include <stdio.h> #include <threads.h> #include <stdlib.h> thread_local int counter = 0; // 每个线程有自己的counter副本 int thread_func(void *arg) { counter++; // 修改线程本地的counter printf("Thread %ld: counter = %d\n", (long)arg, counter); return 0; } int main() { thrd_t t1, t2; thrd_create(&t1, thread_func, (void *)1); thrd_create(&t2, thread_func, (void *)2); thrd_join(t1, NULL); thrd_join(t2, NULL); printf("Main thread: counter = %d\n", counter); return 0; } </syntaxhighlight> '''可能的输出:''' <pre> Thread 1: counter = 1 Thread 2: counter = 1 Main thread: counter = 0 </pre> == 实现原理 == TLS的实现通常依赖于操作系统和编译器的协作: <mermaid> graph TD A[程序启动] --> B[为TLS变量分配存储空间] B --> C[主线程初始化] C --> D[创建新线程] D --> E[为新线程分配独立的TLS存储] E --> F[线程访问自己的TLS副本] </mermaid> == 实际应用场景 == 1. '''错误码存储''':如C库的<code>errno</code>通常实现为TLS变量 2. '''线程特定缓存''':避免锁竞争 3. '''随机数生成器状态''':保持每个线程的独立状态 == 高级主题:动态TLS == 除了语言级别的TLS支持,操作系统还提供API级别的TLS: * Windows: <code>TlsAlloc()</code>, <code>TlsGetValue()</code>, <code>TlsSetValue()</code> * POSIX: <code>pthread_key_create()</code>, <code>pthread_getspecific()</code>, <code>pthread_setspecific()</code> 示例(POSIX): <syntaxhighlight lang="c"> #include <pthread.h> #include <stdio.h> pthread_key_t key; void destructor(void *value) { free(value); // 清理线程特定数据 } void *thread_func(void *arg) { int *data = malloc(sizeof(int)); *data = pthread_self(); // 使用线程ID作为示例数据 pthread_setspecific(key, data); printf("Thread %lu: data = %d\n", pthread_self(), *(int *)pthread_getspecific(key)); return NULL; } int main() { pthread_key_create(&key, destructor); pthread_t t1, t2; pthread_create(&t1, NULL, thread_func, NULL); pthread_create(&t2, NULL, thread_func, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_key_delete(key); return 0; } </syntaxhighlight> == 性能考量 == TLS访问通常比普通变量访问慢,因为: * 需要通过额外的内存引用(如通过线程环境块) * 某些架构需要特殊的指令支持 性能模型可以表示为: <math> T_{access} = T_{base} + T_{tls\_overhead} </math> == 限制与注意事项 == 1. TLS变量不能是自动存储期(不能声明在函数内非static) 2. 动态库中的TLS可能有平台特定的行为 3. 大量使用TLS可能增加线程创建开销 4. 某些嵌入式平台可能不支持TLS == 总结 == 线程局部存储是多线程编程中的重要工具,它: * 提供线程隔离的数据存储 * 避免不必要的同步开销 * 简化线程安全代码的编写 * 有语言级别和API级别两种实现方式 正确使用TLS可以显著提高多线程程序的可靠性和性能。 [[Category:编程语言]] [[Category:C]] [[Category:C 语言高级特性]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)