我正在研究一个使用互斥锁来保护全局双精度的例子,但是我得到了错误 -
0x77b6308e处的未处理异常 Lab7.exe:0xC0000005:访问冲突 写位置0x00000068。
我认为这与访问分数有关? (全球双倍)
#include <windows.h>
#include <iostream>
#include <process.h>
double score = 0.0;
HANDLE threads[10];
CRITICAL_SECTION score_mutex;
unsigned int __stdcall MyThread(void *data)
{
EnterCriticalSection(&score_mutex);
score = score + 1.0;
LeaveCriticalSection(&score_mutex);
return 0;
}
int main()
{
InitializeCriticalSection(&score_mutex);
for (int loop = 0; loop < 10; loop++)
{
threads[loop] = (HANDLE) _beginthreadex(NULL, 0, MyThread, NULL, 0, NULL);
}
WaitForMultipleObjects(10, threads, 0, INFINITE);
DeleteCriticalSection(&score_mutex);
std::cout << score;
while(true);
}
更新:
在将循环设置为1000而不是10来解决问题之后,错误仍然存在,但是当我注释掉引用互斥锁的代码时,错误没有发生。
CRITICAL_SECTION score_mutex;
EnterCriticalSection(&score_mutex);
LeaveCriticalSection(&score_mutex);
InitializeCriticalSection(&score_mutex);
DeleteCriticalSection(&score_mutex);
更新2
线程按照惯例返回0(这是一个漫长的一周!)
我尝试在与互斥量相关的代码中添加回来,并且程序将编译并运行正常(除了竞争条件问题与双重当然)与CRITICAL_SECTION,InitializeCriticalSection和DeleteCriticalSection全部添加回来。问题似乎使用EnterCriticalSection或LeaveCriticalSection,因为当我添加它时错误再次出现。
答案 0 :(得分:13)
代码中的剩余错误在于对WaitForMultipleObjects()
的调用。您将第3个参数设置为0
(FALSE
),以便主线程在10个线程的任何完成后立即解锁。
这导致在所有线程完成之前执行对DeleteCriticalSection()
的调用,当其中一个(可能)其他线程启动并调用EnterCriticalSection()
时,会创建访问冲突。
答案 1 :(得分:4)
你的写作超出了threads[10]
数组的结尾:
for (int loop = 0; loop < 1000; loop++){
threads[loop];
}
threads
只有10码!
答案 2 :(得分:4)
您的问题是WaitForMultipleObjects没有等待所有线程完成,导致临界区段被过早删除。根据{{3}},第三个参数是
bWaitAll [in]
如果此参数为TRUE,则在发出&gt; lpHandles数组中所有对象的状态时,函数将返回。如果为FALSE,则当将任何一个&gt;对象的状态设置为发信号时,该函数返回。在后一种情况下,返回值表示对象&gt;其状态导致函数返回。
将此值设置为0,在任何一个线程完成时返回。这导致以下DeleteCriticalSection在仍有线程等待访问时运行。
答案 3 :(得分:2)
您还应该将得分声明为易失性,这样您就不会遇到缓存值问题。