重申这一点,因为我的上一个问题已经结束了......这次我试图更好地解释一下......请告诉我你是否需要进一步澄清:
我有一个带有函数doSomething(int count)的类A在A类中,我想打开100个线程,每个线程调用函数doSomething()并在每个线程中传入计数1-100。
这意味着......当第一个线程调用此函数时,它应该调用doSomething(1),第二个线程应该调用doSomething(2),依此类推......
这就是我的代码:
struct input {
A* in;
int count;
};
myFunc(void* data)
{
input* tP = (input*) data;
A* obj = tP->in;
int ct = tP->count;
obj->doSomething(ct);
}
class A {
doSomething(int count);
Thread2doSomething();
}
doSomething(int count)
{
cout<<"Print value is"<<count;
}
Thread2doSomething()
{
for (i = 1 to 100)
{
input myIN;
myIN.in = this;
myIN.count = i;
beginthreadex(myFunc, &myIN);
}
}
我希望上面的代码会在这里产生100个线程..当调用doSomething()时,每个线程都有一个新的1,2,3 ... 100值;
在新线程上每次调用doSomething都应该有一个不同的count值传递给它 - 1,2,3,...到100。
但这不会发生。传递给它的计数值非常随机...通常它会多次获得相同的值...而且根本没有得到一些值。有时传递给doSomething的count值在所有线程中都是相同的...
调用看起来更像是:doSOmething(4),doSomething(4),doSomething(7),doSomething(10),doSomething(10)等等。
希望我澄清了一些事情......请建议。
答案 0 :(得分:2)
您的代码存在两个问题。
第一个问题出在Thread2doSomething()
函数中:您将临时的地址传递给beginthreadex()
。当函数退出时,临时超出范围,并且线程正在访问不再存在的对象。
你有两种方法可以解决这个问题:要么在退出Thread2DoSomething()
之前等待所有线程完成,那么在线程完成工作之前你的堆栈分配对象不会被破坏,或者你在堆上分配每个线程的输入(但是如果你使用原始指针,不要忘记解除分配它们。)
第二个问题是您将相同的输入传递给所有线程,在访问它时修改它(在{内部} {1}}循环),它引入了数据竞赛。因此,您的程序具有未定义的行为。
要解决此问题,您必须为每个线程创建一个for
的新实例,以便在线程尝试访问它时不会覆盖同一个对象。
最后,请记住,无法保证线程的执行顺序。即使您按照特定顺序启动它们,您仍可能会看到打印出的数字的排列,而不是有序序列1..100。
答案 1 :(得分:0)
您正在为所有主题重复使用 input
的一个实例。当然他们从中获取随机数据。由于您无法更改myFunc()
的签名(我认为它是由线程创建函数强制执行的),因此您必须使用动态分配:
Thread2doSomething()
{
input *myIN;
for (i = 1 to 100) {
myIN = new input;
myIN->in = this;
myIN->count = i;
beginthreadex(myFunc, myIN);
}
}
myFunc(void* data)
{
std::unique_ptr<input> tP(reinterpret_cast<input*>(data));
A* obj = tP->in;
int ct = tP->count;
obj->doSomething(ct);
}
在unique_ptr
中使用myFunc()
可确保在myFunc()
终止时取消分配对象。