问题描述
- c语言多线程运行后为什么值会变成这样
-
请问为什么运行下列程序后,gCount的值不为5,而是为一个莫名其妙的随机数啊?
如果说是多线程影响的,那毕竟加和减在两个函数里都限定死了为10000000次,那运算结果应该还是为5啊?
整个运行机制到底是怎样的?
求大神解答!#include
#include
#includevolatile unsigned int gCount=5;
//gCount是全局共享变量,volatile表明不进行优化unsigned __stdcall FirstThreadFunc(void *pArguments)
{
int i;
for(i=0;i<10000000;i++)
{
gCount=gCount+1;
}
return 0;
}unsigned __stdcall SecondThreadFunc(void *pArguments)
{
int i;
for(i=0;i<10000000;i++)
{
gCount=gCount-1;
}
return 0;
}int main()
{
HANDLE hThread[2];
unsigned threadID[2];printf("gCount的初始值为%dn",gCount); hThread[0]=(HANDLE)_beginthreadex(NULL,0,FirstThreadFunc,NULL,0,&threadID[0]); hThread[1]=(HANDLE)_beginthreadex(NULL,0,SecondThreadFunc,NULL,0,&threadID[1]); WaitForSingleObject(hThread[0],INFINITE); WaitForSingleObject(hThread[1],INFINITE); CloseHandle(hThread[0]); CloseHandle(hThread[1]); printf("并发修改后,gCount的值为%dn",gCount); return 0;
}
解决方案
应该是线程安全问题。
解决方案二:
//线程
#if 1
#include
#include
#include
using namespace std;
//声明关键段(临界区)
CRITICAL_SECTION g_csNumber;
//gCount是全局共享变量,volatile表明不进行优化
volatile unsigned int gCount = 5;
unsigned __stdcall FirstThreadFunc(void *pArguments)
{
//进入临界区
//g_csNumber的成员OwningThread代表哪个线程
//拥有临界区,如果OwningThread为NULL,
//则当前线程进入临界区
//如果不为空并当和前线程ID
//不相等则等待
EnterCriticalSection(&g_csNumber);
int i;
for (i = 0; i<10000000; i++)
{
gCount = gCount + 1;
}
//离开临界区
LeaveCriticalSection(&g_csNumber);
Sleep(50);
return 0;
}
unsigned __stdcall SecondThreadFunc(void *pArguments)
{
//进入临界区
//g_csNumber的成员OwningThread代表哪个线程
//拥有临界区,如果OwningThread为NULL,
//则当前线程进入临界区
//如果不为空并当和前线程ID
//不相等则等待
EnterCriticalSection(&g_csNumber);
int i;
for (i = 0; i<10000000; i++)
{
gCount = gCount - 1;
}
//离开临界区
LeaveCriticalSection(&g_csNumber);
return 0;
}
int main()
{
HANDLE hThread[2];
unsigned threadID[2];
printf("gCount的初始值为%dn", gCount);
//初始化临界区
InitializeCriticalSection(&g_csNumber);
hThread[0] = (HANDLE)_beginthreadex(NULL, 0, FirstThreadFunc, NULL, 0, &threadID[0]); //第5个参数,0为运行状态,CREATE_SUSPENDED为挂起状态,阻塞
hThread[1] = (HANDLE)_beginthreadex(NULL, 0, SecondThreadFunc, NULL, 0, &threadID[1]); //第5个参数,0为运行状态,CREATE_SUSPENDED为挂起状态,阻塞
WaitForSingleObject(hThread[0], INFINITE); //若为零则不等待,也就不会输出子线程函数里面的内容
WaitForSingleObject(hThread[1], INFINITE); //若为零则不等待,也就不会输出子线程函数里面的内容
CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
printf("并发修改后,gCount的值为%dn", gCount);
return 0;
}
#endif
以上是我的代码,我加了临界区,保证线程互斥,也就是说在线程一给全局变量加的时候,保证线程二不能够对全局变量进行访问,直到线程一访问完之后,才可以,你还是没有理解多线程问题。