Jim's GameDev Blog

Thread 小结

2017-7-22

总结一下最近使用多线程时的一些东西,主要是用来下载、解压文件。

线程的运算时分配到的时间片的多少不要依赖线程优先级,优先级并不可靠,不同操作系统对于线程的优先级的策略是有差异的。

多线程是将计算量分配到不同的线程上,并行处理,以达到提升计算效率,提高fps的目的,所以并不会减少计算量,更不会减少电量的消耗。相反,由于增加了线程之间的切换和同步的开销,原则上来说反而会增加一些耗电量。

能够并行的线程数量并不是无限多的,而是和CPU核心的数量相等。CPU核心数量越多,可以并行的线程数量就越多。 对于运算密集型的算法来说,创建并运行的线程数达到CPU核心数量后,再创建运行新的线程,并不会提高性能。因为CPU已经满负荷了,再要增加工作量是无效的。对于非运算密集型的算法来说,可以创建大于CPU核心数量的线程数,来保证CPU时刻都处于满负荷的工作状态。

在 Unity Editor 中创建的线程,是属于 Unity.exe 这个进程的,所以对于持续工作的线程来说,必须手动释放线程资源,否则直到 Unity.exe 这个进程被释放的时候,线程资源才会被系统回收。

多线程的内存分配是无法在 Unity 的 Profie 中看出来具体分配位置的,这就给查找内存泄露增加了难度,所以在处理这一块的时候每一步都很小心,由于涉及代码都比较可控,所以还算可以。但是当代码规模、人员规模变大之后,光靠内部自省是无法做到的,所以这里推荐一个工具UWA的多线程内存Profile,据说用过的都说好 :)

尽量使用线程池,而不是手动创建销毁Thread。线程池在线程的管理上更高效。线程池通过挂起、重用线程,并在长时间不用时销毁线程,以达到更高效的使用线程,这比自己手动管理更方便也更安全。

禁用Abort,这个话题是老生常谈了,别被它的字面意思给骗了。

volatile 只保证每次存取时从主存中存取数据,而不是从高速缓存中,但是不保证操作的原子性,这一点一定要注意。Interlocked 保证是原子操作,由于是通过内存地址获取值,所以同样具有 volatile 的特性。