Nodejs 不能像 java 和 .net 那样拥有内置的线程 API。如果添加线程,语言本身的性质就会改变。不可能将线程添加为一组新的可用类或函数。
Nodejs 10.x 添加了工作线程作为实验,现在自 12.x 起稳定。我浏览了几个博客,但可能由于缺乏知识而不太了解。它们与线程有何不同。
Nodejs 不能像 java 和 .net 那样拥有内置的线程 API。如果添加线程,语言本身的性质就会改变。不可能将线程添加为一组新的可用类或函数。
Nodejs 10.x 添加了工作线程作为实验,现在自 12.x 起稳定。我浏览了几个博客,但可能由于缺乏知识而不太了解。它们与线程有何不同。
Javascript 中的工作线程有点类似于浏览器中的 WebWorkers。它们不与主线程或彼此共享对任何变量的直接访问,它们与主线程通信的唯一方式是通过消息传递。此消息通过事件循环同步。这避免了多个线程尝试访问相同变量的所有经典竞争条件,因为两个单独的线程无法访问 node.js 中的相同变量。每个线程都有自己的一组变量,影响另一个线程变量的唯一方法是向它发送一条消息并要求它修改自己的变量。由于该消息通过该线程的事件队列同步,因此在访问变量时不存在经典竞争条件的风险。
另一方面,Java 线程与 C++ 或本机线程相似,因为它们共享对相同变量的访问,并且线程是自由时间分片的,因此在线程 A 中运行的函数 A 中间,执行可能会被中断,而函数 B 在线程 B 中运行可以跑。由于两者都可以自由访问相同的变量,因此存在各种可能的竞争条件,除非手动使用线程同步工具(例如互斥锁)来协调和保护对共享变量的所有访问。这种类型的编程通常是很难找到并且几乎不可能可靠地重现并发错误的根源。虽然对于某些系统级的事情或更实时的代码来说功能强大且有用,但除了非常资深和经验丰富的开发人员之外,任何人都很容易犯下代价高昂的并发错误。而且,它'
node.js 试图通过将线程分离到它们自己的变量空间并强制它们之间的所有通信通过事件队列同步来避免经典的并发错误。这意味着 threadA/functionA 永远不会被任意中断,并且您的进程中的一些其他代码会更改它正在访问的一些共享变量,而它没有查看。
node.js 还有一个支持,它可以运行一个可以用任何语言编写的 child_process,并且可以在需要时使用本机线程,或者可以使用附加 SDK 将本机代码和真正的系统级线程直接挂钩到 node.js (它通过 SDK 接口与 node.js Javascript 通信)。而且,事实上,许多 node.js 内置库正是这样做的,以展示需要对 nodejs 环境进行该级别访问的功能。例如,文件访问的实现使用本地线程池来执行文件操作。
因此,尽管如此,仍然可能发生某些类型的竞争条件,这与访问外部资源有关。例如,如果两个线程或进程都试图做自己的事情并写入同一个文件,它们显然会相互冲突并产生问题。
因此,在 node.js 中使用 Workers 在访问外部资源时仍然需要注意并发问题。node.js 保护每个 Worker 的局部变量环境,但对外部资源之间的争用无能为力。在这方面,node.js Worker 与 Java 线程有相同的问题,程序员必须为此编写代码(独占文件访问、文件锁定、每个 Worker 的单独文件、使用数据库来管理存储的并发性等。 .)。