我有一个游戏中的对象列表,这些对象可能每秒运行多次复杂的碰撞测试,也可能不运行。
因为这种碰撞测试非常昂贵,所以每个对象都有一个预先计算的潜在碰撞候选者的列表。在每个模拟步骤开始时,该列表都会被清除并重新填充。当 A 和 B 的球形碰撞盒(围绕实际碰撞盒)相交时,对象 A 是对象 B 的潜在候选者。
潜在碰撞候选列表的预计算当前是在同一线程上完成的,但我想将其移至不同的线程。 对于少量对象,这已经可以正常工作,但是我创建的对象越多,每个对象的候选列表就越经常以某种方式始终为空。
这就是两个线程正在做的事情:
主题#1:
主题#2:
线程 #1 每秒比线程 #2 运行得更频繁(这是预期的行为)。
只要其中一个线程对任何候选列表具有写访问权限,我就会使用 lock(...){ } 。但不知何故,我添加到场景中的对象越多,每个对象的候选列表就越频繁地为空。这会导致许多对象不再与任何对象发生碰撞,因为它们的候选列表通常是空的,而它们中应该至少有一个对象。
如何正确同步?
System.Collections.Generic命名空间中的集合类 包括列表和字典
。这些课程提供 与之前相比,改进了类型安全性和性能 System.Collections 类。然而,System.Collections.Generic 类不提供任何线程同步;用户代码必须 在添加或删除项目时提供所有同步 多个线程并发。 我们建议使用并发集合类 System.Collections.Concurrent 命名空间,因为它们提供类型 安全性以及更高效和完整的线程安全性。
List<T>
不是线程安全的,看看 线程安全集合
System.Collections.Concurrent 命名空间包括几个 线程安全且可扩展的集合类。多种的 线程可以安全有效地添加或删除这些项目 集合,无需用户额外同步 代码。当您编写新代码时,请使用并发集合类 同时将多个线程写入集合。如果你是 仅从共享集合中读取,然后您可以使用其中的类 System.Collections.Generic 命名空间。
您可以在被认为是线程安全的System.Collections.Concurrent下使用ConcurrentBag Class。