简体   繁体   English

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

[英]how to insert vector only once in multiple thread

I have below code snippet. 我有下面的代码片段。

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 will be called by multiple thread, and I want g_vec will be inserted items only once which is a bit similar as singleton instance . func将由多个线程调用,我希望g_vec仅插入一次项目,这与singleton instance有点类似。 And about singleton instance , I found there is a DCLP issue. 关于singleton instance ,我发现存在DCLP问题。

Question : 问题
1. My above code snippet is thread safe, is it has DCLP issue? 1.我上面的代码段是线程安全的,是否存在DCLP问题?
2. If not thread safe, how to modify it? 2.如果不是线程安全的,该如何修改?

Your code has a data race. 您的代码存在数据争用。

The first check outside the lock is not synchronized with the insertion inside the lock. 锁外部的第一张支票与锁内部的插入不同步。 That means, you may end up with one thread reading the vector (through .empty() ) while another thread is writing the vector (through .insert() ), which is by definition a data race and leads to undefined behavior. 这意味着,您可能最终会遇到一个线程(通过.empty() )读取向量的情况,而另一个线程正在通过.insert() )写入向量的结果, 根据定义 ,这是一个数据竞争,并导致未定义的行为。

A solution for exactly this kind of problem is given by the standard in form of call_once . 标准以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( ... ); });
}

In your example, it could happen that second reentrant thread will find a non empty half initialized vector, that it's something that you won`t want anyway. 在您的示例中,有可能第二个可重入线程将找到一个非空的半初始化向量,这是您始终不想要的。 You should use a flag, and mark it when initialization job is completed. 您应该使用一个标志,并在初始化作业完成时对其进行标记。 Better a standard one, but a simple static int will do the job as well 更好的是一个标准的,但是一个简单的static 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()
    }

    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM