【问题标题】:Why is this function-level static variable not thread-safe in AIX and Solaris?为什么这个函数级静态变量在 AIX 和 Solaris 中不是线程安全的?
【发布时间】:2018-08-25 07:50:49
【问题描述】:

我有这个简单的功能:

bool foo(const std::string& str)
{
    static const std::string ky[] = { "KeyWord1", "KeyWord2", "KeyWord3" };

    static const std::set<std::string> kySet(ky, ky+ sizeof(ky)/sizeof(ky[0]));

    return kySet.find(str) != kySet.end();
}

它基本上保存了一组预先设置的关键字,并测试给定的字符串是否是其中一个关键字。

我使用static,因为我只想要一份预设变量的副本。

这将在多线程环境和不同架构上运行。但是,有人告诉我这在 Linux 上只是线程安全的,但在 AIX 和 Solaris 上会中断。

我不明白它为什么会坏?

【问题讨论】:

  • 数组和集合都需要什么?您的编译器是否过时无法处理 C++11 初始化程序列表?
  • @Someprogrammerdude 是的,它在 C++03 遗留代码库中。
  • C++03 不是线程安全的。
  • 旁白:您可能应该在问题中提到 c++03。
  • 魔术静态是 C++14 的一个特性。你 a) 确定你的编译器支持 C++14 吗? b) 将您的代码编译为 C++14?

标签: c++ multithreading thread-safety solaris aix


【解决方案1】:

引用自 03 标准 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf

第 6.7 节

允许一个实现执行早期初始化 相同下具有静态存储时长的其他本地对象 允许实现静态的条件 在命名空间范围内初始化具有静态存储持续时间的对象 (3.6.2)。否则第一次初始化这样的对象 控制通过它的声明;考虑这样的对象 在其初始化完成时进行初始化。

没有提到线程;因此,您应该考虑函数静态不是线程安全的,除非该函数是在单线程时调用的。

【讨论】:

  • 注意:这在 C++14 中用“神奇的静态”改变了, 以线程安全的方式初始化。
  • @JesperJuhl 这就是我引用 03 标准的原因——因为它是 OP 正在使用的版本。
【解决方案2】:

只有在编译器不实现 C++ 标准时才会如此。否则,标准保证具有静态存储持续时间的变量的线程安全动态初始化,请参阅[stmt.dcl]

在控制第一次通过其声明时执行具有静态存储持续时间或线程存储持续时间的块范围变量的动态初始化;这样的变量在其初始化完成时被认为已初始化。如果初始化抛出异常退出,说明初始化未完成,下次控件进入声明时会再次尝试。 如果控制在变量初始化的同时进入声明,则并发执行将等待初始化完成。 [...]

(重点是我的)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 2015-07-24
    相关资源
    最近更新 更多