📜  “抢”依赖性推论(1)

📅  最后修改于: 2023-12-03 14:48:44.833000             🧑  作者: Mango

“抢”依赖性推论

“抢”依赖性推论是一种常见的程序设计技术,用于提高程序的并发性能。它基于两个假设:

  1. 大部分程序的执行时间都用于等待I / O。
  2. 当一个线程阻止其他线程的执行时,可以试图“抢占”依赖它的线程,使其获得更多的CPU时间。
原理

“抢”依赖性推论通过在等待I / O的线程之间来回切换,来充分利用CPU的时间。当线程A发出I / O请求时,线程A会被软件挂起,CPU可以转而处理其他线程,这将降低CPU利用率。然而,由于假设1,线程A的 I / O请求不太可能立即满足。因此,为了最大化CPU利用率,“抢”依赖性推论会重新调度其他线程,使它们能够运行更长时间。如果另一个线程B依赖线程A完成的任务,那么当线程B运行时(通常在线程A准备好继续之前),线程A可能被“抢占”,并且线程B可以获得更多的CPU时间来完成其工作。这个过程可以一直循环下去,直到线程A的I / O请求完成。

实践

在实践中,“抢”依赖性推论往往被用于事件驱动的程序中。例如,在GUI应用程序中,用户的键盘和鼠标输入通常会导致触发事件,然后程序必须对这些事件进行响应。当某个事件处理程序访问I / O资源时,程序可以切换到处理其他事件的代码,而不是等待I / O请求完成。这减少了事件处理程序中CPU的空闲时间,从而提高了程序的并发性能。

代码示例

下面是一个基于Node.js的代码示例,使用“抢”依赖性推论来提高异步读取文件的并发性能。

const fs = require('fs');

function readFiles(paths, callback) {
  const results = [];
  let count = paths.length;

  for (let i = 0; i < paths.length; i++) {
    fs.readFile(paths[i], (err, data) => {
      if (!err) {
        results[i] = data;
      }
      if (--count === 0) {
        callback(results);
      }
    });
  }
}

在上面的代码中,我们读取每个文件的操作是非阻塞的。当我们发起每个异步读取操作时,线程不会阻塞并等待操作完成,它会继续执行后续的代码。当文件读取完成时,回调函数会被调用。在回调函数中,我们对结果数组进行更新,并且如果所有文件都已经读取,我们会调用回调函数,并传递结果数组。

这段代码利用了“抢”依赖性推论来提高并发性能。当一个异步文件读取操作等待I / O时,程序会启动另一个读取操作。如果其中一个操作首先完成,则完成更少依赖的操作的线程可以执行更多时间,并且完成阻塞另一个操作的线程(从而充分利用CPU),直到它完成读取I / O并调用回调函数。