在C99中使用__thread

5

我希望使用 __thread 存储类定义一些线程特定的变量。但是有三个问题让我犹豫:

  1. c99 标准真的支持吗?更重要的是,编译器支持得如何?
  2. 这些变量会在每个线程中初始化吗?
  3. 非多线程程序将如何处理它们?像普通全局变量一样吗?

2
作为对已收到的答案的补充,线程局部存储将计划纳入即将发布的标准C1x中。 - Jens Gustedt
2个回答

6

针对您的具体问题:

  1. 不,它不是C99的一部分。在n1256.pdf(C99 + TC1/2/3)或原始的C99标准中都找不到它的提及。
  2. 是的,__thread变量在每个新线程中都以其初始化值开始。
  3. 从程序行为的角度来看,线程局部存储类变量在非多线程程序中的行为与普通全局变量基本相同。但是,它们确实会产生更多的运行时成本(内存和启动时间),并且可能存在关于线程局部变量大小和数量限制的问题。所有这些都相当复杂,并且取决于您的程序是静态链接还是动态链接以及变量是位于主程序还是共享库中...

除了实现C/POSIX(例如errno等)之外,线程局部存储类实际上并不是非常有用,我认为它基本上是一个绕过以上下文指针或类似方式传递必要状态的支撑。您可能认为它可以用于解决不接受上下文指针的破碎接口,如qsort,但不幸的是,没有保证qsort将在调用qsort的同一线程中调用比较函数。它可能会将作业分解并在多个线程中运行。对于大多数其他接口,这种解决方法也是如此。


1
当然,线程本地数据总是有点儿欺骗性的,但这并不意味着你有时候不需要欺骗。 - Adrian Ratnapala
在这里想提一下 gnulib。它有一个线程本地存储 (tls) 模块,可以处理大多数平台/编译器。如果你正在编写 (L)GPL 软件,请考虑使用它。我不会开始编写不依赖于平台的代码而没有它——它可以节省你的生命和减少头痛。 - rockdaboot
嗯,gnulib并不能帮助您编写跨平台的软件。它只能帮助您编写一些针对某些N古怪遗留平台硬编码的平台相关hack,除此之外没有其他作用。其中大部分hack都不是线程安全的,并且存在各种问题和边角情况的bug。 - R.. GitHub STOP HELPING ICE

3

1
所以,对于(1),答案是“不;它不在C99标准中”。 - Jonathan Leffler
它被列为C99编辑中的存储类别说明符。http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/C99-Thread_002dLocal-Edits.html - Steve-o
@Steve-o:这并不意味着它与C99有任何关系。相反,该文档只是展示了如何修改C99以包括“__thread”关键字。即将推出的C1x预计将包括线程本地存储类,但它绝对不是C99的一部分。 - R.. GitHub STOP HELPING ICE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接