如何解决用于在C ++中维护静态局部变量的服务数据的线程安全性?

问题描述:

请考虑以下情况。我们有一个带有静态局部变量的C ++函数:

Consider the following scenario. We have a C++ function with a static local variable:

void function()
{
    static int variable = obtain();
    //blahblablah
}

该函数需要从多个线程调用同时,所以我们添加一个关键部分,以避免并发访问静态局部:

the function needs to be called from multiple threads concurrently, so we add a critical section to avoid concurrent access to the static local:

void functionThreadSafe()
{
    CriticalSectionLockClass lock( criticalSection );
    static int variable = obtain();
    //blahblablah
}

但这样就够了吗?我的意思是有一些魔法,使变量被初始化不超过一次。因此,运行时保存的一些服务数据指示每个静态局部是否已经被初始化。

but will this be enough? I mean there's some magic that makes the variable being initialized no more than once. So there's some service data maintained by the runtime that indicates whether each static local has already been initialized.

上述代码中的关键部分是否也保护服务数据?

Will the critical section in the above code protect that service data as well? Is any extra protection required for this scenario?

C ++说你的静态变量应该只被初始化一次 - 然而C ++ does not'

C++ says that your static variable should only be initialized once - however C++ doesn't deal with threads(yet).

gcc(atleast on * nix系统)可以安全地保护多个线程初始化这样一个静态变量。根据 http:// social。 msdn.microsoft.com/Forums/en/vcgeneral/thread/12f8e2c7-d94d-4904-8c79-a0b0d1088e0b ,msvc不 - 在这种情况下,你必须自己锁定初始化。

gcc(atleast on *nix systems) does the proper magic to safely guard multiple threads initializing such a static variable. According to http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/12f8e2c7-d94d-4904-8c79-a0b0d1088e0b , msvc does not - and in such a case you'll have to lock the initialization yourself.

使用临界区保护初始化应该保护所有这些 - 即你的functionThreadSafe()是ok - (除非 gets()本身调用 functionThreadSafe()

Guarding the initialization with a critical section should protect all this - i.e. your functionThreadSafe() is ok - (unless obtain() itself calls functionThreadSafe()

http://blogs.msdn.com/b/oldnewthing/archive/2004/03/08/85901.aspx 在这方面值得一读。

为了避免意外,我会尝试重写这个,所以你可以初始化 variable 自己,一次,在创建任何线程之前 - 例如

Personally, to avoid surprises I'd try to rewrite this so you can initialize variable yourself, once, before you create any threads - e.g.

static int variable = 0;
void init_variable() //call this once, at the start of main()
{
  variable = obtain();
}

void function() 
{
  //use variable, lock if you write to it
}