如果你为它设计项目,有很多技术可以用来处理多线程。
最普遍和普遍的就是“避免共享状态”。只要有可能,在线程之间复制资源,而不是让它们访问同一个共享副本。
如果您自己编写低级同步代码,则必须记住绝对不要做任何假设。编译器和 CPU 都可能重新排序您的代码,从而在读取代码时创建竞争条件或死锁,这些情况似乎都不可能发生。防止这种情况的唯一方法是使用内存屏障。请记住,即使是最简单的操作也可能会出现线程问题。简单的东西++i
通常不是原子的,如果多个线程访问i
,你会得到不可预知的结果。当然,仅仅因为您已经为变量分配了一个值,这并不能保证新值对其他线程是可见的。编译器可能会推迟实际将其写入内存。同样,内存屏障强制它“刷新”所有未决的内存 I/O。
如果我是你,如果可能的话,我会使用比简单的锁/互斥体/监视器/关键部分更高级别的同步模型。有一些CSP库可用于大多数语言和平台,包括 .NET 语言和本机 C++。
这通常会使竞争条件和死锁难以检测和修复,并允许可笑的可扩展性。但是这种范式也有一定的开销,因此每个线程完成的工作可能比使用其他技术时要少。它还要求整个应用程序专门针对这种范式进行结构化(因此改造现有代码很棘手,但由于您是从头开始,所以问题不大——但您仍然不熟悉)
另一种方法可能是Transactional Memory。这更容易适应传统的程序结构,但也有一些限制,而且我不知道有多少生产质量的库用于它(STM.NET 最近发布,可能值得一试。英特尔有一个 C++带有内置于语言中的 STM 扩展的编译器)
但无论您使用哪种方法,您都必须仔细考虑如何将工作拆分为独立的任务,以及如何避免线程之间的串扰。任何时候两个线程访问同一个变量,你都有一个潜在的错误。并且任何时候两个线程访问同一个变量或只是访问同一地址附近的另一个变量(例如,数组中的下一个或前一个元素),数据必须在内核之间交换,迫使它从 CPU 缓存刷新到内存,然后读入另一个核心的缓存。这可能会对性能造成重大影响。
哦,如果您确实使用 C++ 编写应用程序,请不要低估该语言。您必须先详细学习该语言,然后才能编写健壮的代码,更不用说健壮的线程代码了。