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 Workers 具有与 Java 线程相同的问题,程序员必须为此编写代码(独占文件访问、文件锁、每个 Worker 的单独文件、使用数据库来管理存储并发性等。 .)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)