Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c+中的竞争条件或内存损坏+;螺纹_C++_Multithreading_Stdthread - Fatal编程技术网

C++ c+中的竞争条件或内存损坏+;螺纹

C++ c+中的竞争条件或内存损坏+;螺纹,c++,multithreading,stdthread,C++,Multithreading,Stdthread,我很难精确定位竞争条件或内存损坏的确切来源。代码后面显示了我解决问题的尝试 我的结构如下: class A { protected: // various variables // 1. vector that is assigned value on B, C, D constructor and not // modified while in thread // 2. various ints // 3. double array that is acc

我很难精确定位竞争条件或内存损坏的确切来源。代码后面显示了我解决问题的尝试

我的结构如下:

class A
{
protected:
   // various variables
   // 1. vector that is assigned value on B, C, D constructor and not 
   //   modified while in thread
   // 2. various ints
   // 3. double array that is accessed by B, C, D
   // here that are used by B, C and D
public:
   virtual void execute() = 0;
};

class B : A
{
public:
   B(...){};
   bool isFinished();
   void execute(); //execute does a very expensive loop (genetic algorithm)
}

class C : A
{
public:
   C(...){};
   bool isFinished();
   void execute();
}

class D : A
{
public:
   D(...){};
   bool isFinished();
   void execute();
}

class Worker
{
private:
   A& m_a;
   Container& m_parent;
public:
   // Worker needs a reference to parent container to control a mutex 
   // in the sync version of this code (not shown here)
   Worker(A& aa, Container& parent) : m_a(aa), m_parent(parent) {}
   executeAsynchronous();
}

class Container
{
private:
   std::vector<Worker> wVec;
public:
   addWorker(Worker w); //this does wVec.push_back(w)
   start();
}

void Worker::executeAsynchronous(){
    while(!a.isFinished())
        m_a.execute();
}

void Container::start(){
    std::thread threads[3];
    for (int i=0; i<wVec.size(); i++){
        threads[i] = std::thread(&Worker::executeAsynchronous,
                                                std::ref(wVec[i]));
    }
    for (int i=0; i<wVec.size(); i++){
        threads[i].join();
    }
}
代码应该生成线程以异步运行
execute()
,但是我有以下两个问题:

  • 一个线程比2个、3个或4个线程快,并且有更好的结果(通过在一个线程中运行遗传算法得到更好的优化),我已经读到了这一点,但这是在哪里发生的?我怎样才能证实这是真的

  • 两个或多个线程:结果变得非常糟糕,不知何故,一些东西正在被破坏或损坏。然而,我无法准确地指出这一点。我从代码中的不同位置执行
    cout
    ed,每个线程只执行一个继承类的
    execute()
    ,也就是说,每个线程运行
    B、C或D的
    execute()
    ,不会跳转或干扰其他线程。我把
    m_parent.mutex.lock()和
    m_parent.mutex.unlock()放在
    a.execute()周围的那一刻有效地使多线程代码成为单线程,结果再次变得正确

  • 我试图:

  • 移除
    B、C和D
    中的指针,这些指针在将
    工作者
    推回
    容器
    的向量后可能会悬空。我现在将一份副本传递给
    推回
  • 使用
    emplace\u back
    代替
    push\u back
    ,但这没有什么区别
  • 使用
    vector.reserve()
    避免重新分配和失去引用,但没有区别
  • 使用
    std::ref()
    ,因为我发现std::thread创建了一个副本,并且我希望修改元素
    wVec[I]
    ,之前我只是将
    wVec[I]
    传递给线程
  • 我相信通过执行上面的1-4,它们没有任何区别,通过运行代码单线程,它可以完美地工作,这不是超出范围的情况。 另外,线程或容器之间没有数据交换,我知道
    std::vector
    不是线程安全的

    如果你能抽出时间帮我解决这个问题,我将不胜感激

    EDIT1:根据Constantin Pan的通知,这是我的RandomNumberGenerator类,它是一个静态类,我使用
    RandomNumberGenerator::getDouble(a,b)

    EDIT4:Deque container也有罪-M4rc

    Each sample counts as 0.01 seconds.
      %   cumulative   self              self     total           
     time   seconds   seconds    calls   s/call   s/call  name    
    14.15     28.60    28.60 799662660     0.00     0.00  std::_Deque_iterator
    

    如果涉及到遗传算法,请确保随机数生成器是线程安全的。我曾经用
    cstdlib

    中的
    rand()
    自己解决过这个问题(速度减慢和结果不正确),如果您想帮助您找出代码不起作用的原因,您必须实际发布不起作用的代码。这在多线程代码中尤其重要。减少应用程序,直到它尽可能小,并且仍然保留错误。如果仍然需要帮助,请发布代码。探查器可能会解释速度减慢的原因,但我猜stl分配器是罪魁祸首。我也遇到过类似的问题,但线程明显增多。对于GRIN,可能会动态分配指向您推回的任何对象的指针,而不是将对象本身推回——只是为了看看这是否与损坏问题有关。@M4rc我已经用我的发现更新了问题(Edit2),我将尝试您的建议。非常注意,我已经编辑并添加了我的rng类,这是一个静态类,我相信它应该是线程安全的
    //rng.h
    class RandomNumberGenerator
    {
    private:
        static std::mt19937 rng;
    
    public:
        static void initRNG();
        static int getInt(int min, int max);
        static double getDouble(double min, double max);
    };
    
    //rng.cpp
    std::mt19937 RandomNumberGenerator::rng;
    
    void RandomNumberGenerator::initRNG()
    {
        rng.seed(std::random_device()());
    }
    
    int RandomNumberGenerator::getInt(int min, int max)
    {
        std::uniform_int_distribution<std::mt19937::result_type> udist(min, max);
        return udist(rng);
    }
    
    double RandomNumberGenerator::getDouble(double min, double max)
    {
        std::uniform_real_distribution<> udist(min, max);
        return udist(rng);
    }
    
    Flat profile:
    
    Each sample counts as 0.01 seconds.
      %   cumulative   self              self     total           
     time   seconds   seconds    calls   s/call   s/call  name    
     17.97     70.09    70.09  1734468     0.00     0.00  std::mersenne_twister_engine //SYNC
     18.33     64.98    64.98  1803194     0.00     0.00  std::mersenne_twister_engine //ASYNC
      6.19     63.41     8.93  1185214     0.00     0.00  std::mersenne_twister_engine //Single thread
    
    Each sample counts as 0.01 seconds.
      %   cumulative   self              self     total           
     time   seconds   seconds    calls   s/call   s/call  name    
    14.15     28.60    28.60 799662660     0.00     0.00  std::_Deque_iterator