为什么__thread必须遵循extern或static

时间:2019-02-08 16:40:37

标签: c multithreading thread-safety thread-local-storage

我正在阅读Kerrisk's book,并看到以下内容作为31-4的注释,

  
      
  • 如果__threadstatic关键字在变量的   声明。
  •   
  • 线程局部变量的声明可以包含初始化程序,方式与普通的全局变量或静态变量相同   声明。
  •   
  • C地址(&)运算符可用于获取线程局部变量的地址。
  •   

我想知道关键字必须位于externstatic之后的原因。没有它们就不能使用吗?

它的示例代码,

extern

2 个答案:

答案 0 :(得分:2)

线程局部变量的标准C存储类说明符为_Thread_local。该标准还在§6.11 Future directions中说:

  

6.11.5存储类说明符

     

存储类说明符的放置位置,而不是在声明的开头   声明中的说明符是过时的功能。

因此,该标准说存储类关键字(staticexternauto —不要使用它!— register —同上— {{1} }和_Thread_local应该出现在声明的开头。在出现typedefstatic并出现extern的地方,书中的建议是_Thread_localstatic应该在第一位,extern在第二位。

当然,这本书使用的是_Thread_local,而不是__thread。这是特定于编译器(实现)的关键字,其行为与标准C _Thread_local和Microsoft的_Thread_local类似。

thread local storage个文档上的GCC文档(添加了重点):

  

在用户级别,可以使用新的存储类关键字__declspec(thread)看到扩展名。例如:

__thread
     

__thread int i; extern __thread struct state s; static __thread char *p; 说明符可以与__threadextern说明符一起单独使用,但不能与其他存储类说明符一起使用。与staticextern一起使用时, static必须立即出现在另一个存储类说明符之后。

     

__thread说明符可以应用于类的任何全局,文件作用域的静态,函数作用域的静态或静态数据成员。它可能不适用于块范围内的自动或非静态数据成员。

因此,您所看到的是特定于GCC的线程本地存储的表示法,正如我所指出的和GCC手册所指出的,存储类信息应首先出现在声明中(而GCC明确表示{{1 }}在__thread__thread之后。

另请参阅Common variable attributes

答案 1 :(得分:1)

重新阅读您引用的文字(强调我的意思):

  
      
  • __ thread关键字必须紧跟在static或extern关键字之后,如果在变量的声明中指定了两者之一,则必须紧随其后。
  •   

因此,如果两者均未指定,则此子句不适用。

至于“为什么”,如果主张是正确的(我怀疑它是正确的,但陈述不准确),这只是“ {@ 1}}来自的“ GNU C”的语法问题。您可以在C11标准中查找等效的__thread的语法要求。