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

Issue with calling a function on multiple threads

本文关键字:函数 问题 调用 线程      更新时间:2023-10-16

由于我之前的问题被关闭,所以重新发布这个。这次我试着解释得更清楚一些。如果你需要进一步的说明,请告诉我:

我有一个函数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个线程,每个线程将有一个新的值,计数1,2,3…当它调用doSomething();

在一个新线程上每次调用doSomething都应该有一个不同的count值传递给它——1,2,3,…100 .

但这不会发生。传递给它的计数值是相当随机的…通常它会多次得到相同的值……没有得到任何值。有时传递给doSomething的count值在所有线程中是相同的…

调用看起来更像这样:doSOmething(4), doSOmething(4), doSOmething(7), doSOmething(10), doSOmething(10)等等。

希望我已经说清楚了…请建议。

你的代码有两个问题。

第一个问题是在Thread2doSomething()函数中:您将临时的地址传递给beginthreadex()。当函数退出时,临时对象将超出作用域,并且线程正在访问一个不再存在的对象。

你有两种可能来解决这个问题:要么你等待所有的线程完成之前退出Thread2DoSomething(),这样你的堆栈分配的对象不会被销毁之前线程已经完成了他们的工作,或者你分配每个线程的输入堆(但不要忘记释放它们,如果你使用原始指针)。

第二个问题是您将相同的输入传递给所有线程,并且在访问(在for循环内)时修改它,这引入了数据竞争。因此,您的程序具有未定义行为

要解决这个问题,你必须为每个线程创建一个新的input实例,这样当线程试图访问它时,你就不会覆盖同一个对象。

最后,请记住,不能保证线程的执行顺序。即使以特定的顺序开始,您可能仍然会看到打印出的数字排列,而不是有序的序列1..100。

您正在为所有线程重用 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);
}

myFunc()中使用unique_ptr将确保在myFunc()终止时对象被释放。