为什么当前大多数应用程序是多线程的,为什么要使用支持多线程的库

原文

http://www.nynaeve.net/?p=198
        大部分的Win32 程序在运行的时候,其进程中至少有一段时间是超过一个线程的,尽管有时程序没有明确的创建一个线程。这是因为有些系统API 会为了它们自己的目的而创建线程。
        例如,控制台Ctrl-C/Ctrl-Break 事件默认情况下是被单独的线程处理的。(在内部,CSRSS在容器进程中创建一个新线程,该线程之后调用kernel32 的函数来调用活动控制台的处理列表。这也是kernel32必须在所有的进程中有同样的基地址的一个原因,另外,CSRSS 缓存kernel32中Ctrl-C 的分发函数并假设它在所有的客户进程中的地址是一样的。)这可能会导致潜在的意外线程问题,这取决于控制台控制处理程序所进行的操作。例如,如果一个控制台控制程序向控制台输出,除非显式使用一些形式的同步方法,否则这个输出行为将不会与在此控制台上执行的内部线程的任何I/O 操作进行同步。
        这也是现在的VS 编译器完全避开单线程CRT 的原因,作为替代品,其支持CRT的多线程变体。对于游戏来说,为了节省极少的锁定开销而使用一个单线程CRT 可以获得的好处是有限的,因为线程可能因为奇怪的原因而终止运行(比如一个控制台控制处理器的注册操作)。在一个主要是单线程的程序中, 临界区代码的执行速度足够快,与正在执行的实际处理开销相比,CRT 锁所产生的任何开销都是微不足道的。
        Win32 API的很大一部分是通过使用工作线程来完成任务的,尽管这些线程对于进程镜像来说有有限的可见性。例如, WSAAsyncGetHostByName 使用一个工作线程来同步调用 gethostbyname 并通过一个Windows 消息将结果发送给请求者。甚至调试程序也将导致在被调试进程中生成一个线程以满足调试器的侵入过程。
        由于大部分的Win32程序或多或少都会遇见多线程的情况,除了CRT,Win32的其它组件也渐渐放弃了对于纯单线程操作最后的支持。例如, low fragmentation heap (LFH) 不再支持 HEAP_NO_SERIALIZE,该标志使得堆的内置临界区不可用。这种情况下,就像CRT,完全不获取锁而安全的运行的情况是非常有限的,而这仅仅获得了比较小的好处,不如承担一下为了获得临界区锁而调用的函数所带来的开销。(进入一个没有被拥有的临界区而不涉及到内核模式转移的时候,其所消耗的时间是非常少的。在一个典型的单线程应用程序中,所有的临界区几乎都是被拥有的,或者因为递归调用而被线程拥有)

猜你喜欢

转载自blog.csdn.net/qq_18218335/article/details/78262412