我正在写一个 Minecraft 的克隆版本,我真的想为世界生成、更新 block 、光传播等实现多线程。 我将所有加载的 block 存储在 HashMap “chunk_map”中。
在 chunk_map 上放置互斥锁会破坏多线程的全部目的,因为每个线程的大部分工作都在 chunk_map 上迭代。
如果我的想法是正确的,那么在 map 中插入一个新 block 应该不是问题(在最坏的情况下,线程可能会跳过刚刚添加的 block ) 但是删除一个chunk肯定是个问题。
使用 shared_ptr 而不是 iterator_type 的散列映射实现是否可以解决从映射中删除 am 元素而其他线程遍历该映射的问题? 还是有一些不同的、更简单的方法?
编辑: 我想完全避免同步线程,因为我不希望世界生成、 block 更新等限制渲染性能。
我希望主线程渲染当前加载的所有 block 。 我还希望“更新程序线程”更新每个加载 block 中的每个 block ,等等。 以及加载和卸载 block 的“世界线程”。
最佳答案
不幸的是,你的问题是基于一个错误的前提:
If what i'm thinking is correct, inserting a new chunk into the map shouldn't be problem (in the worst case scenario a thread might skip a chunk that has just been added) But deleting a chunk would definitely be a problem.
不,你错了。最坏的情况比这更糟。考虑:
- 线程 A 构造一个新 block 。
- 线程 A 将该 block 添加到映射中。
- 线程 B 在映射中看到新 block 的条目。
- 线程 B 尝试访问该 block ,但由于代码优化和重新排序写入的硬件,它看不到线程 A 在步骤 1 中进行的写入。
糟糕,你的程序刚刚崩溃了。
你推理中的关键缺陷,这是一个非常常见的缺陷,如果你想成为一名成功的程序员,你绝对必须在推理中修正它,它认为如果你违反明确的规则,唯一可能出错的地方是你可以预见的事情。这种推理在计算机编程领域是绝对的死亡。
所以,事实上,绝对最坏的情况比我上面说的还要糟糕。您违反了您正在使用的类的要求,该类的实现会因平台而异。您绝对无法知道哪里会出错。
关于c++ - 多个线程在 C++ 中访问 std::map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57205647/