c – 多线程环境中的静态局部变量初始化

假设有一个函数(可能是成员函数)

SomeType foo()
{
    static SomeType var = generateVar();
    return var;
}

如果foo从多个线程同时被称为“第一次”,将如何初始化var?

>是否保证generateVar()在任何情况下只被调用一次(如果使用的话)?
>是否保证foo会在任何情况下多次调用时返回相同的值?
>原始或非原始类型的行为有差异吗?

关于C 03:

由C 03标准定义的抽象机不包含一个线程的正式定义,以及如果一个对象被同时访问,程序的结果应该是什么。

没有同步原语的概念,在不同线程中执行的操作的排序,数据竞争等等。因此,根据定义,每个多线程C 03程序都包含未定义的行为。

当然,在实践中,实现确实提供了一个记录的行为,但是在标准中没有指定这个行为应该是什么。因此,我会说这取决于你的编译器。

答案的其余部分将重点放在C11上,它确定了并发操作的语义。

关于C 11:

Is it guaranteed that generateVar() will be called only once in any scenario (if used of course)?

不,不是在任何情况下。

var的初始化保证是线程安全的,因此不会同时输入generateVar(),但是如果generateVar()引发异常,或者由SomeType的复制构造函数或移动构造函数(如果SomeType是UDT) ,当然),那么初次化将在下一次执行流程进入声明时重新尝试 – 这意味着generateVar()将再次被调用。

根据C 11标准关于静态存储持续时间的块范围变量初始化的第6.7 / 4段:

[…] If the initialization exits by throwing an exception, the initialization
is not complete, so it will be tried again the next time control enters the declaration. If control enters
the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for
completion of the initialization. If control re-enters the declaration recursively while the variable is being
initialized, the behavior is undefined. […]

关于你的下一个问题:

Is it guaranteed that foo will return the same value when called multiple times in any scenario?

如果它会设法返回一个值(见上文),那么是的。

Is there a difference in behaviour for primitive or non-primitive types?

不,没有,除了没有这样的东西作为复制构造函数或移动构造函数的原始类型,所以也没有副本初始化将导致抛出异常的风险(除非当然generateVar()抛出)。

http://stackoverflow.com/questions/16734966/static-local-variable-initialisation-in-multithreaded-environment

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c – 多线程环境中的静态局部变量初始化