条件变量不工作,但添加 std::cout 后,它工作
Posted
技术标签:
【中文标题】条件变量不工作,但添加 std::cout 后,它工作【英文标题】:The conditional variable is not working but after adding std::cout, it is working 【发布时间】:2015-06-15 07:40:33 【问题描述】:我的项目由两个线程组成:一个主线程和另一个处理另一个窗口内容的线程。所以,当主线程想要请求另一个窗口更新自己时,它调用了如下的绘制函数:
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;
draw 函数只是通知另一个线程收到了新任务。
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;
运行另一个线程,但如果我在SubApplication::draw()
的开头添加std::cout << "Draw\n";
,它会正常运行。我正在寻找它发生的原因以及修复它的常用方法是什么?
【问题讨论】:
您需要在此处显示 SSCCE。这留下了太多的猜测。根据我们在此处看到的内容,我提供了一个“提示”答案。这是 SSCCE 的开始:paste.ubuntu.com/11718487 说白了,你好像不明白条件变量的全部目的,就是提供一个原子的“解锁等待”功能,避免等待已经发生的事情。 【参考方案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
而另一个线程正在修改它的竞争?这可能会立即导致死锁。
此外,您的代码声称“等待所有子应用程序完成绘制”,但没有调用任何等待函数。所以它实际上是在旋转而不是等待,这很糟糕。
【讨论】:
【参考方案2】:首先,在task_start_mutex
锁定下发送task_start_condition
信号。
考虑在线程创建期间锁定该互斥体以避免明显的竞争。
第三:您似乎有几个以“逻辑任务”(绘制、启动)命名的互斥锁。然而,实际上,互斥锁保护资源,而不是“逻辑任务”。因此,以他们应该保护的共享资源命名它们是一种很好的做法。 _(在这种情况下,我的印象是单个互斥体可能就足够/更好了。但我们无法从显示的代码中确定)。
【讨论】:
以上是关于条件变量不工作,但添加 std::cout 后,它工作的主要内容,如果未能解决你的问题,请参考以下文章