如何在多个线程中只插入一次向量

时间:2014-06-12 08:29:39

标签: c++ multithreading

我有以下代码段。

std::vector<int> g_vec;

void func()
{
    //I add double check to avoid thread need lock every time.
    if(g_vec.empty())
    {
       //lock
       if(g_vec.empty())
       {
          //insert items into g_vec
       }
       //unlock
    }

    ...
}

func将由多个线程调用,我希望g_vec只插入一次与singleton instance有点相似的项目。关于singleton instance,我发现存在DCLP问题。

问题
1.我上面的代码片段是线程安全的,它有DCLP问题吗? 2.如果不是线程安全,如何修改它?

2 个答案:

答案 0 :(得分:3)

您的代码有数据竞争。

锁外的第一次检查与锁内的插入不同步。这意味着,你可能最终得到一个线程读取向量(通过.empty()),而另一个线程正在写向量(通过.insert()),这是by definition数据竞争并导致未定义的行为。

标准以call_once的形式给出了解决这类问题的方法。

#include<mutex>

std::vector<int> g_vec;
std::once_flag g_flag;

void func()
{
    std::call_once(g_flag, [&g_vec](){ g_vec.insert( ... ); });
}

答案 1 :(得分:-1)

在你的例子中,可能会发生第二个可重入的线程将找到一个非空的半初始化向量,这是你无论如何都不想要的东西。您应该使用标志,并在初始化作业完成时将其标记。更好的标准,但一个简单的静态int也可以完成这项工作

std::vector<int> g_vec;

void func()
{
    //I add double check to avoid thread need lock every time.
    static int called = 0;
    if(!called)
    {
       lock()
       if(!called)
       {
          //insert items into g_vec
          called = 1;
       }
       unlock()
    }

    ...
}