线程被视为轻量级进程。它们实际上会比相同数量的分叉进程运行得更快吗?
2 回答
线程被视为轻量级进程。
哦,不,他们不是。fork
Perl 线程模型与Windows 系统上的模拟交织在一起。在许多方面,在 Perl 中产生一个新线程与派生一个新进程的行为相同:两个产生的控制流都在单独的perl 解释器中运行。也就是说,整个程序状态被复制来制作一个新的解释器。
它们实际上会比相同数量的分叉进程运行得更快吗?
不见得。产生一个新线程是软件方面的,由 perl 完成。分叉是由操作系统(在 *nix 系统上)完成的,它可以利用写时复制技术。这可以使分叉便宜得多。一个小测试:
$ time perl -Mthreads -e'threads->new(sub{threads->exit})->detach for 1 .. 5E3'
real 0m10.651s
user 0m16.421s
sys 0m1.904s
$ time perl -Mthreads -e'fork || exit for 1 .. 5E3'
real 0m2.347s
user 0m0.032s
sys 0m0.516s
这会产生五千个线程/进程。由于它在 Linux 上进行了测试,结果证明生成一个新进程更快。在其他操作系统上可能不是这种情况。
这并不是说 Perl 线程毫无用处:它们提供了许多好处,例如可选共享数据、传递数据的队列、管理共享资源的信号量、线程可以返回值等。在进程之间共享数据的最简单方法(无需using modules) 是pipe
创建两个链接文件句柄的内置函数。
不要混淆对线程一词的不同解释:
内核线程是硬件级的执行线。它们通常不被调度,而是并行运行。每个处理器至少有一个线程。
操作系统线程由操作系统提供。现代操作系统自己调度线程执行(抢占式调度)。通常,所有数据都是共享的,线程只是有不同的堆栈。Perl 线程选择不强调共享属性。
软件线程,也是绿色线程,由软件本身调度,通常通过协作调度。许多具有廉价线程的语言都选择这种模型,例如 Go。两个绿色线程不一定并行运行。协程和绿色线程实际上是相关的概念:两者都描述了并发执行路径。
软件线程有时可以比操作系统线程运行得更快,因为软件可以在程序中方便的地方进行上下文切换。(操作系统线程或进程之间的抢先切换成本更高,因为操作系统内核必须定期运行,并且处理器缓存和寄存器必须在每次上下文切换时使用另一个线程的数据进行更新。这并不重要编写常规应用程序代码)
Perl 线程通常不使用此模型,但是存在协程模块(
Coro
)。