我正在编写一个简单的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。我尝试将它公开,没有任何效果。有什么明显的我想念吗?
答案 0 :(得分:0)
您正在从多个线程访问m_loadedChunks而不进行同步。 您需要锁定共享使用的使用。这里提示很少。
std::mutex mtx; // mutex for critical section
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的会谈。
因此,对于您拥有的任何共享变量,请使用上面的示例作为解决种族问题的一种方法。