C ++多线程应用程序崩溃

时间:2017-04-15 17:07:24

标签: c++ multithreading c++11 dictionary vector

我正在编写一个简单的3D渲染引擎,只是为了让C ++更加熟悉。今天我已经迈出了多线程的第一步,已经遇到了一个问题我无法绕过头脑。当应用程序启动时,它会生成一个由立方体组成的小型类似Minecraft的地形。它们是在主线程中生成的。

现在,当我想要生成更多块时

void VoxelWorld::generateChunk(glm::vec2 chunkPosition) {
    Chunk* generatedChunk = m_worldGenerator->generateChunk(chunkPosition);
    generatedChunk->shader = m_chunkShader;
    generatedChunk->generateRenderObject();
    m_chunks[chunkPosition.x][chunkPosition.y] = generatedChunk;
    m_loadedChunks.push_back(glm::vec2(chunkPosition.x, chunkPosition.y));
}

void VoxelWorld::generateChunkThreaded(glm::vec2 chunkPosition) {
    std::thread chunkThread(&VoxelWorld::generateChunk, this, chunkPosition);
    chunkThread.detach();
}

void VoxelWorld::draw() {
    for(glm::vec2& vec : m_loadedChunks){
        Transformation* transformation = new Transformation();
        transformation->getPosition().setPosition(glm::vec3(CHUNK_WIDTH*vec.x, 0, CHUNK_WIDTH*vec.y));
        m_chunks[vec.x][vec.y]->getRenderObject()->draw(transformation);
        delete(transformation); //TODO: Find a better way
    }
}

我有我的成员函数(一切都是非静态的)generateChunk(),它生成一个Chunk并将其存储在VoxelWorld类中。我有一个存储每个块的2D std::map<..> m_chunks和一个存储生成块的位置的std::vector<glm::vec2> m_loadedChunks

调用generateChunk()可以正常工作。但是当我尝试generateChunkThreaded()应用程序崩溃时!我试着评论generateChunk()的最后一行,然后它不会崩溃。这就是让我困惑的东西! m_loadedChunks只是一个常规的std :: vector。我尝试将它公开,没有任何效果。有什么明显的我想念吗?

2 个答案:

答案 0 :(得分:0)

您正在从多个线程访问m_loadedChunks而不进行同步。 您需要锁定共享使用的使用。这里提示很少。

  1. 将互斥锁声明为类
  2. 的成员
    std::mutex mtx;           // mutex for critical section
    
    1. 每次要访问元素时,使用它来锁定关键部分
    2.   

      std :: lock_guard lock(mtx);

           

      m_chunks [chunkPosition.x] [chunkPosition.y] = generatedChunk;

           

      m_loadedChunks.push_back(glm :: vec2(chunkPosition.x,chunkPosition.y));

      希望有所帮助

答案 1 :(得分:0)

当您有许多线程访问共享资源时,您可以将这些资源作为只读,原子或使用互斥锁进行保护。

因此,对于您的m_loadedChunks成员变量,您可能希望将其包装在锁中。例如:

class VoxelWorld
{
    // your class members and more ...
private:
  std::mutex m_loadedChunksMutex;
}

void VoxelWorld::generateChunk(glm::vec2 chunkPosition)
{
    Chunk* generatedChunk  = m_worldGenerator->generateChunk(chunkPosition);
    generatedChunk->shader = m_chunkShader;

    generatedChunk->generateRenderObject();

    m_chunks[chunkPosition.x][chunkPosition.y] = generatedChunk;

    {
        auto&& scopedLock = std::lock_guard< std::mutex >(m_loadedChunksMutex);
        (void)scopedLock;
        m_loadedChunks.push_back(glm::vec2(chunkPosition.x, chunkPosition.y));
    }
}

scopedLock将自动等待锁定,当代码超出范围时,锁定将被释放。

现在请注意,我有 m_loadedChunks 的互斥锁,而不是涵盖线程可以访问的所有变量的通用互斥锁。这实际上是Herb Sutter在他的&#34; Effective Concurrency&#34;中引入的一个好习惯。课程和他在cppcon的会谈。

因此,对于您拥有的任何共享变量,请使用上面的示例作为解决种族问题的一种方法。

相关问题