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

sha*_*oth 5 c++ concurrency multithreading synchronization

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

void function()
{
    static int variable = obtain();
    //blahblablah
}
Run Code Online (Sandbox Code Playgroud)

该函数需要同时从多个线程调用,因此我们添加一个临界区以避免对静态local的并发访问:

void functionThreadSafe()
{
    CriticalSectionLockClass lock( criticalSection );
    static int variable = obtain();
    //blahblablah
}
Run Code Online (Sandbox Code Playgroud)

但这还够吗?我的意思是有一些魔法可以使变量初始化不超过一次.因此,运行时维护了一些服务数据,指示每个静态本地是否已经初始化.

上述代码中的关键部分是否也会保护该服务数据?这种情况需要额外的保护吗?

nos*_*nos 5

C++说你的静态变量应该只被初始化一次 - 但是C++不会处理线程(但是).

gcc(至少在*nix系统上)可以正确地保护多个初始化这种静态变量的线程.根据http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/12f8e2c7-d94d-4904-8c79-a0b0d1088e0b,msvc没有 - 在这种情况下你将不得不自己锁定初始化.

使用临界区保护初始化应该保护所有这一切 - 即你的functionThreadSafe()是正常的 - (除非obtain()它自己调用functionThreadSafe()

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

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

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
}
Run Code Online (Sandbox Code Playgroud)