多线程环境中的静态局部变量初始化 [英] Static local variable initialisation in multithreaded environment

查看:134
本文介绍了多线程环境中的静态局部变量初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

如何 var 如果 foo 将同时从多个线程调用'初次'?


  1. 是否保证 generateVar()在任何情况下都只调用一次(如果使用)?

  2. 保证 foo 在任何情况下调用多次时都会返回相同的值?

  3. -primitive types?


解决方案

关于C ++ 03:



由C ++ 03标准定义的抽象机器不包含线程的正式定义,一个程序应该是一个对象被并发访问。



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



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



其余的答案将集中在C ++ 11,它定义并发操作的语义。 p>

关于C ++ 11:


保证 generateVar()在任何情况下只被调用一次(如果使用当然)?



b $ b

否,不是在任何情况下。



var 的初始化保证是线程安全的,因此 generateVar 不会同时输入,但是如果 generateVar()抛出异常,或者通过<$ c的复制构造函数或move构造函数抛出异常$ c> SomeType (如果 SomeType 是一个UDT,当然),那么下次执行流程时将重新尝试初始化 generateVar()将被再次调用。



+11标准关于以静态存储持续时间初始化块范围变量:


<如果初始化通过抛出异常退出,初始化
不是完整的,所以在下一次控制进入声明时将再次尝试。如果控制在变量初始化时同时输入
声明,并发执行将等待
完成初始化。如果控制在变量
初始化时递归地重新输入声明,则行为是未定义的。 [...]


关于您的下一个问题:


是否保证foo在任何情况下多次调用时会返回相同的值?



原始类型或非原始类型的行为是否有区别? p>

不,除了没有像原始类型的复制构造函数或move构造函数那样的东西,所以有也没有复制初始化会导致抛出异常的风险(除非当然 generateVar() throws)。


Suppose there is a function (member function possibly)

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

How var will be initialised if foo will be called 'for first time' from multiple threads simultaneously?

  1. Is it guaranteed that generateVar() will be called only once in any scenario (if used of course)?
  2. Is it guaranteed that foo will return the same value when called multiple times in any scenario?
  3. Is there a difference in behaviour for primitive or non-primitive types?

解决方案

Concerning C++03:

The abstract machine defined by the C++03 Standard does not contain a formal definition of what a thread is, and what the outcome of a program should be if an object is accessed concurrently.

There is no notion of synchronization primitive, ordering of operations performed in different threads, data race, and so on. Therefore, by definition, every multi-threaded C++03 program contains undefined behavior.

Of course, in practice implementations do provide a documented behavior, but there is nothing in the Standard that specifies what this behavior should be. Therefore, I would say it depends on your compiler.

The rest of the answer will focus on C++11, which does define the semantics of concurrent operations.

Concerning C++11:

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

No, not in any scenario.

The initialization of var is guaranteed to be thread-safe, so generateVar() won't be entered concurrently, but if an exception is thrown by generateVar(), or by the copy constructor or move constructor of SomeType (if SomeType is a UDT, of course), then initialization will be re-attempted the next time the flow of execution enters the declaration - which means generateVar() will get called again.

Per paragraph 6.7/4 of the C++11 Standard on the initialization of block-scope variables with static storage duration:

[...] 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. [...]

Concerning your next question:

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

If it will manage to return a value (see above), then yes.

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

No, there isn't, except that there is no such a thing as a copy constructor or move constructor for primitive types, so there is also no risk that copy-initialization will result in throwing an exception (unless of course generateVar() throws).

这篇关于多线程环境中的静态局部变量初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆