我的函数所做的是遍历一个bool数组,并在找到一个设置为false的元素时,将其设置为true。该函数是我的内存管理器单例类的一个方法,它返回一个指向内存的指针。我收到一个错误,我的迭代器似乎循环并最终从头开始,我相信因为多个线程正在调用该函数。
void* CNetworkMemoryManager::GetMemory()
{
WaitForSingleObject(hMutexCounter, INFINITE);
if(mCounter >= NetConsts::kNumMemorySlots)
{
mCounter = 0;
}
unsigned int tempCounter = mCounter;
unsigned int start = tempCounter;
while(mUsedSlots[tempCounter])
{
tempCounter++;
if(tempCounter >= NetConsts::kNumMemorySlots)
{
tempCounter = 0;
}
//looped all the way around
if(tempCounter == start)
{
assert(false);
return NULL;
}
}
//return pointer to free space and increment
mCounter = tempCounter + 1;
ReleaseMutex(hMutexCounter);
mUsedSlots[tempCounter] = true;
return mPointers[tempCounter];
}
我的错误是循环中断言的断言。我的问题是如何修复函数,是多线程引起的错误?
编辑:添加了一个互斥锁以保护mCounter变量。没变。错误仍然存在。
答案 0 :(得分:1)
我不能说错误是否是由多线程引起的,但我可以说你的代码不是线程安全的。
您可以使用
释放锁定ReleaseMutex(hMutexCounter);
然后访问tempCounter和mUsedSlots:
mUsedSlots[tempCounter] = true;
return mPointers[tempCounter];
两者都不是常量。这是一场数据竞赛,因为您没有正确地序列化对这些变量的访问。
将其更改为:
mUsedSlots[tempCounter] = true;
const unsigned int retVal = mPointers[tempCounter];
ReleaseMutex(hMutexCounter);
return retVal;
然后至少你的代码是线程安全的,这是否解决了我不能说的问题,试试看。在具有多个内核的机器上,由于数据竞争而发生非常奇怪的事情。
作为一般的最佳实践,我建议您查看一些C ++ 11同步功能,例如std::mutex
和std::lock_guard
,这样可以使您免于自我,因为std :: lock_guard会自动锁定,因此你不能忘记,在这种情况下,你不能在不经意间做得太快。这也可以使您的代码更具可移植性。如果您还没有使用C ++ 11,那么请使用提升等效项。