静态结构体初始化的线程安全性。

7

鉴于以下示例:

struct test
{
    const char* data;
    const int number;
};

struct test* foo()
{
    static struct test t = {
        "this is some data",
        69
    };
    return &t;
}

调用foo是线程安全的吗?换句话说,结构体是否以线程安全的方式仅在一个线程中初始化?这是否会因为编译语言是C还是C++而有所不同?


1
在C++中是线程安全的。我不知道C语言是否也是这样。 - Ted Lyngmo
1
C和C++的初始化规则非常不同,因此您应该一次只询问一种语言。 - Lundin
1
@Lundin:另一方面,提出关于两种语言之间的差异的问题可能是有用的。然而,这需要回答者了解两种语言的规则。 - Andreas Wenzel
3
在C++中,自C++11以来,t的初始化是线程安全的。 在C++11之前,它不是线程安全的(因为早期标准根本没有与线程相关的规定)。 我相信在C中,t的初始化也是线程安全的,主要是因为在C中静态变量只能使用文字(编译时常量)进行初始化[从中我推断出结构将在任何线程访问它之前被初始化]。 - Peter
显示剩余7条评论
2个回答

4

在 C/C++ 的 C++ 11 及以后版本中(早期标准缺乏任何线程机制的规定),这种区别是存在的。

您可以在这里看到:C++ Static local variables">C++ 静态局部变量,C++11 标准保证静态局部变量只初始化一次。对于在多线程环境下确保单一初始化的锁有一个特定的注释:

如果多个线程同时尝试初始化同一个静态局部变量,则初始化仅发生一次(可以使用 std::call_once 来获取类似的行为)。注意:通常实现此功能的方式使用变体的双重检查锁定模式,该模式将已初始化的本地静态值的运行时开销减少到单个非原子布尔比较。

在 C 语言中,规则已在 C 存储期 中指定:

静态存储期。该存储期为程序的整个执行过程,并且对象中存储的值仅在 main 函数之前初始化一次。所有声明为 static 的对象以及所有既不声明为_Thread_local(自 C11 起),也无内部或外部链接的对象均具有此存储期。


1
这个答案可能正确适用于C ++,但问题也在询问语言C和C ++之间的区别。 - Andreas Wenzel
1
在我看来,一个完整的答案还应该指定C语言中的规则。您链接的文档页面底部包含了一个指向相应C语言文档的链接,其中指定了C语言中的规则。请在C语言文档中搜索“and the value stored in the object is initialized only once, prior to main function.”。 - Andreas Wenzel
@AndreasWenzel,由于您的两条评论,我更新了我的答案。 - Amit
1
你现在已经引用了两种语言的相关规则。然而,你并没有直接回答这个问题。这是否意味着在这两种语言中初始化是线程安全的?如果是这样的话,那么你可能需要在答案中明确说明。 - Andreas Wenzel

0

自C++11以来,对象初始化将仅由一个线程完成,其他线程将等待其完成。请参考thread


1
这个答案可能对C++是正确的,但问题也在询问C和C++之间的区别。 - Andreas Wenzel

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