1

我的程序基于在 main( )。main() 处理“世界”本身的更新,而函数 updateDisplay() 在监视器上显示“世界”的内容。updateDisplay() 由单独的 C++11 线程(在 main() 中启动)运行,并通过传递的引用访问“世界”。

我的问题是我遇到了罕见的崩溃,因为在下面 updateDisplay() 的(简化)代码摘录中,向量 world.m_grid[i][j].m_rabbit 偶尔会在“ if (!world.m_grid[i][j].m_rabbit.empty())" 签入 updateDisplay(),但在后续访问 m_rabbit[0] 向量成员之前,导致“向量下标超出范围”错误。

for (int i = 0; i < rows; ++i)
{
    for (int j = 0; j < columns; ++j)
    {

        if (!world.m_grid[i][j].m_rabbit.empty())
        {
            s_rabbit_64.setScale(absTileScale * world.m_grid[i][j].m_rabbit[0].m_size, absTileScale * world.m_grid[i][j].m_rabbit[0].m_size);
            s_rabbit_64.setPosition(x * k + (12 * absTileScale), y * (i - winFocus.y) + (12 * absTileScale));
            window.draw(s_rabbit_64);
        }
    }
}

我的问题是,如何锁定 world.m_grid[i][j].m_rabbit 向量,以便 main() 在 updateDisplay() 线程访问它时无法更改它?我认为这是通过使用 std::mutex 实现的,但我一直无法找到一个指南,让我对此有足够的理解,以便将其应用到我的程序中。我希望这足够清楚理解(程序比这个摘录大得多,我不想做大量的文本转储),请要求澄清你需要的任何点。

感谢您的关注。

[编辑] 拼写

4

2 回答 2

3

欢迎来到多线程的狂野和毛茸茸的世界。坐下;你会在这里很长时间。比如,你剩下的编程生涯有点长。这很可怕,充满了背叛和微妙的错误,如果你能做对的话,也会得到很好的回报:-)

实际上,在这种情况下,您在识别特定错误方面做得非常好。您需要的是有一个互斥锁来保护线程之间共享的所有访问和状态突变。在您的情况下:在清除向量之前将互斥锁锁定在主线程中,并在完成后解锁互斥锁。同样,在访问之前将互斥锁锁定在处理线程中,并在完成后将其解锁。在这种特殊情况下,您可能最终会锁定整个双 for 循环。

这个答案很好地解释了互斥锁在做什么。


是的,有更快、更优雅的做事方式,但现在让我们坚持正确性。

于 2013-01-29T05:19:58.297 回答
1

您需要识别代码的关键部分。从您上面发布的内容来看,似乎任何修改 world.m_grid[i][j].m_rabbit 的操作都是关键部分。

然后,您需要某种同步技术,以便在任何时候只有一个线程可以进入特定的关键部分(例如互斥锁)。

你需要在网上搜索一些好的阅读材料——或者更好地找到一本好的编程书籍并花一些时间阅读并发章节。

于 2013-01-29T05:44:01.970 回答