【问题标题】:Thread safety of local static array in C99C99中局部静态数组的线程安全
【发布时间】:2017-01-25 15:32:21
【问题描述】:

以下是线程安全的,因为每个数组元素只能由一个线程访问(包括此处未显示的真实世界部分):

static bool myArray[THREAD_COUNT] = {false}; // Only used in DoSomething()

void DoSomething(uint8_t threadIndex)
{
   myArray[threadIndex] = true;
   // Real world function is more complex
}

现在考虑以下代码:

void DoSomething(uint8_t threadIndex)
{
   static bool myArray[THREAD_COUNT] = {false};
   myArray[threadIndex] = true;
   // Real world function is more complex
}

这个函数也是线程安全的吗(特别是考虑到在函数第一次调用时发生的数组初始化,而不是在启动时)?

【问题讨论】:

  • 全局变量或局部static变量基本相同。您所做的所有更改实际上只是范围(实际上)。并且本地 static 变量的初始化是线程安全的。
  • 我们确定static局部变量的初始化是在第一次调用子程序时进行的吗?我不是 - 有人可以确认吗?
  • @linuxfan 我认为没有标准要求,因为它不会影响语义。但常见的实现是在编译期间将具有静态存储的初始化变量放入二进制文件的专用.data 部分。实际上,强制编译器将 one time 初始化代码包含到函数中是没有意义的。这样的代码将需要一些额外的跟踪(一些其他静态变量?)。更新:嘿,看,标准要求...
  • “考虑到在第一次调用函数时发生的数组初始化,而不是在启动时” - 这是错误的。静态对象的初始化在调用main 之前完成。赋值不是初始化。
  • 我不会赌这个。为了安全起见,请使用 C11 _Thread_local。作为个人说明:我宁愿将数组放在函数体之外,并正确记录。

标签: c arrays thread-safety c99 static-variables


【解决方案1】:

很安全。所有具有静态存储持续时间的对象都在程序启动之前初始化。这意味着甚至在任何线程发挥作用之前。

5.1.2 Execution environments:

定义了两种执行环境:独立和托管。在 在这两种情况下,程序启动都发生在指定的 C 函数 由执行环境调用。 所有具有静态存储的对象 持续时间应在之前初始化(设置为其初始值) 程序启动。 这种初始化的方式和时间是 否则未指定。程序终止将控制权返回给 执行环境。

(强调我的)。

C99 没有线程的概念。但这就是我从标准中解释上述引用的方式。

【讨论】:

  • OT:是我的印象还是人们仍然更喜欢 POSIX 线程而不是 C11 线程?
  • 有趣。等等...我是否知道在第一次函数调用时初始化本地静态变量?在 C++ 中是这样的吗?
  • 你应该更新你的链接到当前标准(实际上是最终草案):port70.net/~nsz/c/c11/n1570.html
  • @Olaf 这个问题专门针对 C99。所以,引用C99(草案)是合适的。
  • @KeineLust C11 线程支持尚未广泛使用(特别是 glibc 尚未提供)。所以,我猜大多数人仍然更喜欢 POSIX 线程。
猜你喜欢
  • 2014-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
相关资源
最近更新 更多