我正在尝试使用SDL2的线程库为C ++中的多线程编写一个线程安全的任务队列。
在所有线程上运行的线程函数如下:
int threadFunc(void * pData)
{
ThreadData* data = (ThreadData*)pData;
SDLTaskManager* pool = data->pool;
Task* task = nullptr;
while (true)
{
SDL_LockMutex(pool->mLock);
while (!pool->mRunning && pool->mCurrentTasks.empty())
{
//mutex is unlocked, then locked again when signal received
SDL_CondWait(pool->mConditionFlag, pool->mLock);
if (pool->mShuttingDown)
return 0;
}
//mutex is locked at this stage so no other threads can alter contents of deque
//code inside if block should not be executed if deque is empty
if (!pool->mCurrentTasks.empty())
{
/*out of range error here*/
task = pool->mCurrentTasks.front();
pool->mCurrentTasks.pop_front();
}
if (task != nullptr)
{
pool->notifyThreadWorking(true);
data->taskCount++;
}
else
{
pool->stop();
SDL_UnlockMutex(pool->mLock);
continue;
}
SDL_UnlockMutex(pool->mLock);
task->execute();
SDL_LockMutex(pool->mLock);
pool->notifyThreadWorking(false);
pool->mCompleteTasks.push_back(task);
SDL_UnlockMutex(pool->mLock);
task = nullptr;
}
return 0;
}
正如您所看到的,根据代码中的注释,if块中出现超出范围的错误,其中deque为空。但是,在那里进行检查以确保仅在deque不为空时才执行代码。互斥锁被SDL_CondWait锁定,因此没有其他线程能够对双端队列进行更改,直到该互斥锁再次解锁为止。
生产者代码如下:
SDL_LockMutex(pool->mLock);
for (int i = 0; i < numTasks; i++)
{
pool->mCurrentTasks.push_back(new Task());
}
pool->mRunning = true;
SDL_CondBroadcast(pool->mConditionFlag);
SDL_UnlockMutex(pool->mLock);
if块中的代码正在被执行的事实表明,在评估if (!pool->mCurrentTasks.empty())
时,deque有成员数据,但在到达task = pool->mCurrentTasks.front();
时却没有。我对mutex的理解'这不应该是可能的。怎么会这样?