while get-character-from-remote:
print-to-screen character
监控键盘和发送的循环也很简单:
while get-character-from-keyboard:
send-to-remote character
但问题是,你必须同时做这件事。如果没有线程,代码现在必须看起来更像这样:
loop:
check-for-remote-character
if remote-character-is-ready:
print-to-screen character
check-for-keyboard-entry
if keyboard-is-ready:
send-to-remote character
这个逻辑,即使在这个故意简化的例子中,没有考虑到现实世界通信的复杂性,也是相当模糊的。然而,使用线程,即使在单个核上,两个伪代码循环也可以独立存在,而无需交错它们的逻辑。由于这两个线程大部分都是 I/O 绑定的,因此它们不会给 CPU 带来沉重的负载,即使严格地说,它们比集成循环更浪费 CPU 资源。
如果您的任务是 CPU 限制的而不是 I/O 限制的,那么线程实际上会降低系统速度。表现会受到影响。在很多情况下,是很多。(如果您丢弃了太多 CPU 绑定线程,“ Thrashing”是一个常见问题。更改活动线程所花费的时间比运行线程本身的内容所花费的时间还要多。)此外,上面的逻辑如此简单的原因之一是,我非常谨慎地选择了一个简单(和不现实)的例子。如果您想要回显屏幕上输入的内容,那么当您引入共享资源锁定时,您将面临一个新的伤害世界。只有一个共享的资源,这不是一个问题,但它开始成为一个更大的问题,因为你有更多的资源共享。
回答您的第一个问题: 多线程的重点通常是在一个应用程序中同时执行多个任务。网络上的典型例子是发送和接收邮件的电子邮件程序,以及接收和发送页面请求的 Web 服务器。(注意,像 Windows 这样的系统基本上不可能只运行一个线程,甚至只运行一个进程。运行 Windows 任务管理器,您通常会看到一个活动进程的长列表,其中许多进程将运行多个线程。)
回答您的第二个问题: 大多数进程/线程不受 CPU 限制(即不连续不间断地运行) ,而是经常停止并等待 I/O 完成。在等待期间,其他进程/线程可以在不“窃取”等待代码的情况下运行(即使在单个核心计算机上)。
这也是为什么分支预测很重要的原因。如果您有一个 If 语句,需要从 RAM 加载一个值,但是 If 和 else 语句的主体使用已经加载到寄存器中的值,处理器可以在计算条件之前执行一个或两个分支。一旦条件返回,处理器将应用相应分支的结果并丢弃另一个分支。在这里执行可能无用的工作可能比切换到另一个线程要好,后者可能会导致混乱。