问题原因:由于多线程访问造成数据不统一导致的。
测试案例代码:
code:
// 全局资源
DWORD dwArray[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
DWORD *pdwArray[10];
// 资源调用函数
void printArray(const char* szpThradName)
{
for (int i = 0; i<10; i++)
{
DbgPrintMine("%s == %d\r\n", szpThradName, *pdwArray[i]);
Sleep(1000);
}
}
DWORD WINAPI ChildThread()
{
while (true)
{
memset(pdwArray, NULL, sizeof(dwArray));
for (int i = 0; i < 10; i++)
{
pdwArray[i] = dwArray + i;
}
printArray("子线程");
}
return 0;
}
DWORD WINAPI MainThread()
{
while (true)
{
memset(pdwArray, NULL, sizeof(dwArray));
for (int i = 0; i< 10; i++)
{
pdwArray[i] = dwArray + i;
Sleep(700);
}
printArray("主线程");
}
return 0;
}
void CTestoneDlg::OnBnClickedButtonMainthread()
{
// TODO: 在此添加控件通知处理程序代码
CreateThread(NULL, NULL, LPTHREAD_START_ROUTINE(MainThread), NULL, NULL, NULL);
}
void CTestoneDlg::OnBnClickedButtonChildthread()
{
// TODO: 在此添加控件通知处理程序代码
CreateThread(NULL, NULL, LPTHREAD_START_ROUTINE(ChildThread), NULL, NULL, NULL);
}
造成原因:两个线程访问的数据未同步。
解决方式:
1、事件临界区(临界资源:一次仅允许一个进程使用的资源称为临界资源)
就是使原先多个进程同时访问的数据每次仅允许一个进程访问,各进程对这个数据的访问时互斥的。
2、HOOK窗口事件
Windwos API
InitializeCriticalSection ----> 初始化一个临界资源对象
VOID InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection // address of critical
// section object
);
code:
// 全局资源
DWORD dwArray[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
DWORD *pdwArray[10];
// 临界区对象
CRITICAL_SECTION mySection;
// 资源调用函数
void printArray(const char* szpThradName)
{
// 添加临界区
EnterCriticalSection(&mySection);
for (int i = 0; i<10; i++)
{
DbgPrintMine("%s == %d\r\n", szpThradName, *pdwArray[i]);
Sleep(1000);
}
// 退出临界区
LeaveCriticalSection(&mySection);
}
DWORD WINAPI ChildThread()
{
while (true)
{
EnterCriticalSection(&mySection);
memset(pdwArray, NULL, sizeof(dwArray));
for (int i = 0; i < 10; i++)
{
pdwArray[i] = dwArray + i;
}
printArray("子线程");
LeaveCriticalSection(&mySection);
}
return 0;
}
DWORD WINAPI MainThread()
{
while (true)
{
EnterCriticalSection(&mySection);
memset(pdwArray, NULL, sizeof(dwArray));
for (int i = 0; i< 10; i++)
{
pdwArray[i] = dwArray + i;
Sleep(300);
}
printArray("主线程");
LeaveCriticalSection(&mySection);
Sleep(1000);
}
return 0;
}
void CTestoneDlg::OnBnClickedButtonMainthread()
{
// TODO: 在此添加控件通知处理程序代码
CreateThread(NULL, NULL, LPTHREAD_START_ROUTINE(MainThread), NULL, NULL, NULL);
}
void CTestoneDlg::OnBnClickedButtonChildthread()
{
// TODO: 在此添加控件通知处理程序代码
CreateThread(NULL, NULL, LPTHREAD_START_ROUTINE(ChildThread), NULL, NULL, NULL);
}
void CTestoneDlg::OnBnClickedButtonInit()
{
// TODO: 在此添加控件通知处理程序代码
// 初始化临界区
InitializeCriticalSection(&mySection);
}