本地静态变量初始化是线程安全的

时间:2016-09-14 09:34:04

标签: c++ c++11 c++14

假设我有一个包含三个静态函数的类:

#include <vector>
#include <iostream>
using namespace std;
#include <thread>


class Employee
{

};

class client
{

public:
    void Doprocessing()
    {
        //is this thread safe in c++11/14
        static int i = CreateEmployee();

        //does it look good to use static variable like this to make it thread safe?
        static int k = ProcessEmploye();
    }

private:


    static int CreateEmployee()
    {
        static Employee * e = new Employee();
        InsertEmployee(e);
        return 1;
    }

    static int  InsertEmployee(Employee *e)
    {
        vec.push_back(e);
        return 1;
    }

    static int ProcessEmploye()
    {
        Employee* e = vec[0];
        //do something with e
        //...
        //.
        //Suppose 10 -20 lines 
        return 1;
    }


    static std::vector<Employee*> vec;
};

std::vector<Employee*> client::vec;

void func()
{
    client cobj;
    cobj.Doprocessing();
}

const int No_Of_Threads = 10;
int main() {


    std::thread * threadpointer = new std::thread[No_Of_Threads];

    std::srand(11);
    for (int i = 0; i < No_Of_Threads; i++)
    {
        threadpointer[i] = std::thread(func);
    }

    for (int i = 0; i < No_Of_Threads; i++)
    {
        threadpointer[i].join();
    }
    delete[] threadpointer;

    std::cout << " Good" << std::endl;
    return 0;
}

我的问题是:
1)如果我使用static int i = Somefunc(),无论somefunc多么庞大,将被称为一次并且线程安全? 2)如果1)的回答是肯定的,对于程序员而言,为了上述目的,使用static int i = SomeFunc()是否合适?

1 个答案:

答案 0 :(得分:2)

是的,它将是线程安全的,但仅限于C ++ 11。静态变量以线程安全的方式初始化,它们通常也称为魔法静态。

有关详情,请参阅此处:http://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables

  

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

另外 - 在你的代码中你调用CreateEmployee();在初始化static i期间,CreateEmployee(也初始化静态变量。这也应该没问题,你可以在下面的标准脚注中找到:

  

实现不得在执行期间引入任何死锁   初始化程序。

至于你的第二个问题,从你所展示的代码中我看不出使用静态变量作为获得线程安全的方法是可以的。

您是否知道将变量指定为函数体内的静态允许您只分配一次?这意味着您的CreateEmployee()将始终返回相同的Employee实例。