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()
,但是我有以下两个问题:
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]
传递给线程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