在多个线程上调用函数的问题

时间:2013-01-17 08:41:55

标签: c++ multithreading

重申这一点,因为我的上一个问题已经结束了......这次我试图更好地解释一下......请告诉我你是否需要进一步澄清:

我有一个带有函数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)等等。

希望我澄清了一些事情......请建议。

2 个答案:

答案 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()终止时取消分配对象。