多线程程序问题,如何让多个线程中的多个线程数据同步问题!

时间:2022-02-15 13:02:14
有一个多线程的程序,当这个程序启动以后,我点鼠健会运行这个程序里的一个MTProc函数,
MTProc函数定义如下:

VOID MTProc()
{
CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)MTItemProc, &tData1, 0, &dwPID); //线程A,任务一
CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)MTItemProc, &tData2, 0, &dwPID); //线程B,任务二
}

我用上面这个函数来启动2个线程,也就是同时启动了两个任务,线程函数定义如下:
DWORD MTItemProc(VOID *pParam)
{
THREADDATA *tData = (THREADDATA*)pParam;
mtExample.Example(THREADDATA->szHttpUrl, THREADDATA->szLocalFilename, THREADDATA->nThreadCount) ;
return 1;
}


在MTProc里我调用了来自MTExample类的Example函数,这个函数本身也是一个多线程的,就是说Example函数本身也会启动多个线程运行。
Example函数会根据MTProc函数传入的参数tData1里的字段nThreadCount来动态创建多个线程,这个线程里使用了2个静态的类变量,分别定义如下:
static INT m_nCompletes; //表示有多少个线程已经结束
static HANDLE m_hMutex; //互斥体


MTExample类里的函数Example定义如下,这个类函数是非静态的:

//hMutex = CreateMutex(NULL, FALSE, L"sanxiaMutex"); //线程互斥体
BOOL HttpExample::Example(INT nCompletes...)
{
//WaitForSingleObject(HttpExample::hMutex, INFINITE); //等待(我不需要让B线程等待,我需要线程A和线程B都同时运行,所以注释了)

for(i=0; i< nThreadCount; i++)
{
CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)HttpExample::ThreadProc_Example...) ; //创建新线程
}

(问题就出来这里,下面这句如果MTProc函数只启动一个线程,运行结果才是正确的,可是如果如最上面MTProc函数所示同时启动2个以上的线程就程序运行会有逻辑错误,运行结果不是我想要的)

while(HttpExample::m_nCompletes != nCompletes); //等待线程(就是使上面循环创建的多个线程)完成任务
SvaeFile(szLocalFilename, nCompletes); //保存文件处理(保存文件会出现逻辑错误,保存的结果不正确,调试发现是nCompletes的数值不正确,在线程A结束过程中被线程B改变了, 如果加上线程互斥体让线程B等待会解决此问题,但是那样线程A和线程B中的多个子线程就不能同时运行了,问题是我需要他们同时运行,该如何处理呢)  
//ReleaseMutex(HttpExample::hMutex);
  
}

应为我需要知道线程何时结束,所以才定义了m_nCompletes


在ThreadProc_Example函数里面通过一些判断改变了HttpExample::m_nCompletes静态变量的值。由于有多个线程在运行,所以m_nCompletes也会被其他的线程所改变,注意这个Example函数里动态创建了一系列的线程。
打个比方会比较直观:

首先MTProc() ----〉启动2个线程A,B

然后A会根据传入的参数动态的创建多个线程如A1,A2...
B同样也会根据传入的参数动态的创建多个线程如B1,B2,B3...

A1,A2和B1,B2,B3都是同时运行的,他们都回根据适当的条件去改变静态变量HttpExample::m_nCompletes的值,这个会出现问题。
如果在Example(...)里创建互斥体,到时可以解决问题,那就是只有等A1,A2运行完以后,再让B1,B2,B3运行,可以我需要让他们都同时运行,因此我就在这里出现问题了,由于我对多线程的处理还不是太了解,还请大家帮忙,应该如何处理,请各位高手给些提示...



交流QQ:154674958





5 个解决方案

#1


因为你需要共享操作的只是一个int,所以没必要用互斥体,用InterlockedIncrement和InterlockedDecrement足够了。如果一定要用互斥体,那么你可以WaitForSingleObject

#2


因为你需要共享操作的只是一个int,所以没必要用互斥体,用InterlockedIncrement和InterlockedDecrement足够了。如果一定要用互斥体,那么你可以WaitForSingleObject进入互斥体,修改m_nCompletes后马上ReleaseMutex。 也就是说尽量减少需要同步的语句数

#3


WaitForSingleObject
如过一等待的话,那B线程就没有和A同时运行了。我需要他们同时跑起来!

#4


想在物理上同时运行几乎不可能, 除非你的系统拥有几十个CPU(所有当前系统中运行的线程--几十个算少的--都能够分配一个CPU还要捎带拐弯多几个CPU运行你的线程). 

就算你用WaitForSingleObject等待, 两个线程之间的时间差也不比系统正常调度线程需要的时间长多少

#5


先创建的A,A创建的B。那B肯定比A滞后。
同时跑起来,应该需要多个CPU。而且,还必须明确的分配哪个线程用哪个CPU来执行。

我觉得楼主,应该再好好理解一下多线程。

一楼说的对。互斥本身就是内核对象,比较慢。用原子锁会快一些。


引用 3 楼 chongchong2008 的回复:
WaitForSingleObject
如过一等待的话,那B线程就没有和A同时运行了。我需要他们同时跑起来!

#1


因为你需要共享操作的只是一个int,所以没必要用互斥体,用InterlockedIncrement和InterlockedDecrement足够了。如果一定要用互斥体,那么你可以WaitForSingleObject

#2


因为你需要共享操作的只是一个int,所以没必要用互斥体,用InterlockedIncrement和InterlockedDecrement足够了。如果一定要用互斥体,那么你可以WaitForSingleObject进入互斥体,修改m_nCompletes后马上ReleaseMutex。 也就是说尽量减少需要同步的语句数

#3


WaitForSingleObject
如过一等待的话,那B线程就没有和A同时运行了。我需要他们同时跑起来!

#4


想在物理上同时运行几乎不可能, 除非你的系统拥有几十个CPU(所有当前系统中运行的线程--几十个算少的--都能够分配一个CPU还要捎带拐弯多几个CPU运行你的线程). 

就算你用WaitForSingleObject等待, 两个线程之间的时间差也不比系统正常调度线程需要的时间长多少

#5


先创建的A,A创建的B。那B肯定比A滞后。
同时跑起来,应该需要多个CPU。而且,还必须明确的分配哪个线程用哪个CPU来执行。

我觉得楼主,应该再好好理解一下多线程。

一楼说的对。互斥本身就是内核对象,比较慢。用原子锁会快一些。


引用 3 楼 chongchong2008 的回复:
WaitForSingleObject
如过一等待的话,那B线程就没有和A同时运行了。我需要他们同时跑起来!