通过引用传递数组的问题

时间:2012-10-09 14:04:43

标签: c++ arrays multithreading

我正在学习线程,我发现了一些简单的例子。

我希望做的是创建5个线程,每个线程将一个随机数分配给20个int的数组。然后最后有另外5个线程将​​这个数组重建为一个更大的100大小的int。

这是我正在尝试的一些先前代码。我希望能够通过引用传递数组,没有运气。

任何想法都会受到赞赏,请记住,我是线程新手

#include <process.h>
#include <windows.h>
#include <iostream>
#include <fstream>
#include <time.h>
//#include <thread>

using namespace std;

void myThread (void *dummy );
void myThread2 (void *dummy );

int main()
{

    ofstream myfile;
    myfile.open ("coinToss.csv");

    int rNum;

    long numRuns;
    long count = 0;
    int divisor = 1;
    float holder = 0;
    int counter = 0;
    float percent = 0.0;

    int array1[1000000];
    int array2[1000000];


    srand ( time(NULL) );

    printf ("Runs (use multiple of 10)? ");
    cin >> numRuns;

    for (int i = 0; i < numRuns; i++)
    {
        _beginthread( myThread, 0, (void *) (array1) );
        _beginthread( myThread2, 0, (void *) (array2) );

    }

}

void myThread (void *param )
{
    int i = *(int *)param;

    for (int x = 0; x < 1000000; x++)
    {
        //param[x] = rand() % 2 + 1;
        i[x] = rand() % 2 + 1;
    }

}

void myThread2 (void *param )
{
    int i[1000000] = *(int *)param;

    for (int = 0; x < 1000000; x++)
    {
        i[x] = rand() % 2 + 1;
    }

}

3 个答案:

答案 0 :(得分:5)

首先要注意的是:

 for (int i = 0; i < numRuns; i++)
    {
        _beginthread( myThread, 0, (void *) (array1) );
        _beginthread( myThread2, 0, (void *) (array2) );

    }

_beginthread的调用立即返回 。他们不等待线程完成,甚至开始。它只是将操作系统调度程序中的线程排队并返回。

但是,上面的代码是main()函数的结尾。我非常怀疑在一个Release版本中你的线程甚至会在整个程序退出之前初始化。您需要构建一种机制,通过该机制,主线程将在程序关闭之前等待工作线程完成其工作。这样做超出了SO帖子的范围,但请查看CreateEvent()WaitForMultipleObjects()

您需要了解的下一件事是您发送给线程的 stuff 的生命周期和所有权语义。您正在将指针传递给数组,这些数组是main()中的自动变量:

 int array1[1000000];
 int array2[1000000];

一旦声明这些数组的范围(此处为main())退出,变量就会停止存在。如果有的话,将指向本地范围的变量的指针传递给工作线程很少是正确的 - 如果本地范围在线程完成之前退出,则永远不会更正。

动态分配这些数组然后将它们的所有权转移到工作线程将解决这个问题。执行此操作时,请在管理这些对象/数组的所有权语义时小心。

答案 1 :(得分:3)

<强> 1。铸造:

注意演员!

void myThread (void *param )
{
  int *i = (int *) param;
  for (int x = 0; x < 1000000; x++)
  {
    i[x] = rand() % 2 + 1;
  }
}

<强> 2。范围:

两个线程都启动了numRuns次。启动它们需要一些时间。也执行它们。 main不应该在不尊重线程的情况下结束。您应该通过WaitForMultipleObjects监视线程。 _beginthread()返回waitable handle

实施:

int main()
{
  long numRuns;
  HANDLE hThread[MAX_WAIT_OBJECTS];

  cin >> numRuns;
  // numRuns to be smaller than MAX_WAIT_OBJECTS/2!!!!


  for (int i = 0; i < numRuns; i++)
  {
     hThread[i * 2]     = _beginthread( myThread, 0, (void *) (array1) );
     hThread[i * 2 + 1] = _beginthread( myThread2, 0, (void *) (array2) );
     // or better use _beginthreadex(...)
  }
  WaitForMultipleObjects(numRuns * 2, hThread, TRUE, INFINITE);
  // bWaitAll flag set TRUE causes this statement to wait until all threads have finished.
  // dwMilliseconds set to INFINITE will force the wait to not timeout.
}

这样main只有在所有线程完成工作后才会完成。

第3。访问:

两个数组都在main部分中声明,因此线程共享它们。为了保护访问权限,您应该引入某种排他性。最简单的是Critical Section Object。当所有threads2只访问array2并且所有threads1只访问array1时,我建议使用2个关键的section对象。关键部分一次只能由一个线程访问。

实现:

CRITICAL_SECTION cs1,cs2; // global

int main()
{
  long numRuns;
  HANDLE hThread[1000];

  // critical section object need to be initialized before aquired
  InitializeCriticalSection(&cs1);
  InitializeCriticalSection(&cs2);

  cin >> numRuns;

  for (int i = 0; i < numRuns; i++)
  {
    hThread[i * 2]     = _beginthread( myThread, 0, (void *) (array1) );
    hThread[i * 2 + 1] = _beginthread( myThread2, 0, (void *) (array2) );
  }
  WaitForMultipleObjects(numRuns * 2, hThread, TRUE, INFINITE);
}

线程(这里只显示一个):

void myThread1 (void *param )
{
  EnterCriticalSection(&cs1); //aquire the critical section object
  int *i = (int *) param;
  for (int x = 0; x < 1000000; x++)
  {
    i[x] = rand() % 2 + 1;
  }
  LeaveCriticalSection(&cs1); // release the critical section object
}

然而:整个故事还不太清楚。您希望多个线程同时从头到尾填充相同的数组。这听起来很奇怪。使用此处描述的临界区对象,无论如何,线程将一个接一个地执行。你的目标究竟是什么?

答案 2 :(得分:1)

其他答案涵盖了要点:还有一个问题通常是个问题(至少在LINUX上:不确定窗口)

int array1[1000000];
int array2[1000000];

将非常大的数组声明为局部变量可能会导致堆栈空间溢出,从而导致程序崩溃。