我只是Go的随便用户,因此,请注意以下事项。
维基百科将绿色线程定义为“由虚拟机(VM)而不是由底层操作系统本地调度的线程”。绿色线程在不依赖任何本机OS功能的情况下模拟多线程环境,并且它们在用户空间而不是内核空间中进行管理,从而使它们可以在不具有本机线程支持的环境中工作。
Go(或更确切地说是两个现有的实现)是仅产生本机代码的语言-它不使用VM。此外,当前运行时实现中的调度程序依赖于OS级线程(即使在GOMAXPROCS = 1时)。因此,我认为谈论Go模式的绿色线程有点滥用。
Go人创造了goroutine术语是为了避免与其他并发机制(例如协程或线程或轻量级进程)混淆。
当然,Go支持M:N线程模型,但它看起来更接近Erlang流程模型,而不是Java绿色线程模型。
这是Go模型相对于绿色线程(在早期JVM中实现的)的一些优点:
对于开发人员而言,可以以透明的方式有效使用多个内核或CPU。使用Go,开发人员应注意并发性。Go运行时将处理并行性。Java绿色线程的实现无法扩展到多个内核或CPU。
系统和C调用对于调度程序而言是非阻塞的(所有系统调用,不仅是在事件循环中支持多路I / O的系统调用)。完成阻塞系统调用后,绿色线程实现可能会阻塞整个过程。
复制或分段堆栈。在Go中,无需为goroutine提供最大堆栈大小。堆栈根据需要递增。结果是,goroutine不需要太多的内存(4KB-8KB),因此可以快乐地产生大量的例程。因此,Goroutine的使用可能很普遍。
现在,解决批评:
使用Go,您不必编写用户空间调度程序:运行时已经提供了它。它是一个复杂的软件,但这是Go开发人员而不是Go用户的问题。对于Go用户来说,其用法是透明的。在Go开发人员中,Dmitri Vyukov是无锁/无等待编程的专家,他似乎对解决调度程序的最终性能问题特别感兴趣。当前的调度程序实现尚不完善,但会有所改善。
同步带来了性能问题和复杂性:Go也是如此。但是请注意,Go模型试图促进并发goroutine中通道的使用和程序的清晰分解,以限制同步复杂性(即通过通信共享数据,而不是共享内存进行通信)。顺便说一下,参考Go实施提供了许多工具来解决性能和并发问题,例如探查器和竞速检测器。
关于页面错误和“多线程伪造”,请注意Go可以在多个系统线程上安排goroutine。当一个线程由于某种原因(页面错误,阻止系统调用)而被阻止时,它不会阻止其他线程继续调度和运行其他goroutine。现在,页面错误确实会阻塞OS线程,所有goroutine都应该在该线程上进行调度。但是实际上,不应将Go堆内存换出。这在Java中是相同的:垃圾收集的语言不能很好地适应虚拟内存。如果您的程序必须以优美的方式处理页面错误,则可能是因为它必须管理一些堆外内存。在这种情况下,
因此,IMO,goroutines不是绿色线程,Go语言和当前的实现方式大多解决了这些批评。