我的项目由两个线程组成:一个主线程和另一个处理另一个窗口内容的线程。因此,当主线程要求另一个窗口更新自身时,它调用draw函数,如下所示:
while contains(currentCardValues, randomNumber + 1) {
draw函数只是告诉另一个线程接收到一个新任务。
void SubApplicationManager::draw() {
// Zero number of applications which has finished the draw counter
{
boost::lock_guard<boost::mutex> lock(SubApplication::draw_mutex);
SubApplication::num_draws = 0;
}
// Draw the sub applications.
for (size_t i = 0; i < m_subApplications.size(); i++)
m_subApplications[i].signal_draw();
// Wait until all the sub applications finish drawing.
while (true){
boost::lock_guard<boost::mutex> lock(SubApplication::draw_mutex);
std::cout << SubApplication::num_draws << std::endl;
if (SubApplication::num_draws >= m_subApplications.size()) break;
}
}
其他线程的主体如下。它等待任务到达然后开始处理:
void SubApplication::signal_draw() {
task = TASK::TASK_DRAW;
{
boost::lock_guard<boost::mutex> lock(task_received_mutex);
task_received = true;
}
task_start_condition.notify_all();
}
问题在于,如果我按原样运行代码,它永远不会运行void SubApplication::thread() {
clock_t start_time, last_update;
start_time = last_update = clock();
//! Creates the Sub Application
init();
while (!done) // Loop That Runs While done=FALSE
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
// Wait here, until a update/draw command is received.
boost::unique_lock<boost::mutex> start_lock(task_start_mutex);
while (!task_received){
task_start_condition.wait(start_lock);
}
// Task received is set to false, for next loop.
{
boost::lock_guard<boost::mutex> lock(task_received_mutex);
task_received = false;
}
clock_t frame_start_time = clock();
switch (task){
case TASK_UPDATE:
update();
break;
case TASK_DRAW:
draw();
swapBuffers();
break;
case TASK_CREATE:
create();
break;
default:
break;
}
clock_t frame_end_time = clock();
double task_time = static_cast<float>(frame_end_time - frame_start_time) / CLOCKS_PER_SEC;
}
}
}
的其他线程,但如果我在task = TASK::TASK_DRAW;
的开头添加std::cout << "Draw\n";
,它将会尽职尽责。我正在寻找它正在发生的原因以及解决它的常用方法是什么?
答案 0 :(得分:1)
作为首发,请在task_start_condition
锁定下发出task_start_mutex
信号。
考虑在创建线程期间锁定该互斥锁,以避免明显的比赛。
第三:似乎你有几个以“逻辑任务”(draw,start)命名的互斥体。然而,实际上,互斥锁保护资源,而不是“逻辑任务”。因此,在他们应该保护的共享资源之后命名它们是一种好习惯。 _(在这种情况下,我得到的印象是单个互斥锁可能足够/更好。但我们无法从显示的代码中确定))。
答案 1 :(得分:1)
boost::lock_guard<boost::mutex> lock(task_received_mutex);
task_received = true;
好的,task_received_mutex
保护task_received
。
boost::unique_lock<boost::mutex> start_lock(task_start_mutex);
while (!task_received){
task_start_condition.wait(start_lock);
}
哎呀,我们正在阅读task_received
而没有拿着保护它的互斥锁。是什么阻止了一个线程在另一个线程正在修改它时读取task_received
的竞争?这可能会立即导致僵局。
此外,您有代码声称“等到所有子应用程序完成绘图”,但没有调用任何等待函数。所以它实际上是旋转而不是等待,这很糟糕。