简而言之,您不能显示并发性和并行性,因为它们可能不是(并发和并行的)。例如,如果您只有一个执行器一个“P”,那么在内部Go运行时模型中,您一次只能运行一个goroutine。

…关于这些是否在单独的threads上运行,似乎有很多困惑。。。

Go最初不是用"threads来定义的,所以这个问题无法回答。这不是很令人满意,但除非你添加诸如“今天在我的系统上”这样的限定符,否则你就只能得到这些了!所以也许你今天想在我的系统上添加限定符。

该规范允许goroutines并行运行,并定义了Go的并发模型,但不需要任何特定的实现。这使得Go实现者可以自由地使用任何看起来合适的工具。我在上面提到了“内部Go运行时模型”,但没有说是哪一个。我指的是今天系统上的那个。

runtimem0

Povilas Versockas在Go运行时中有一个(现在稍微过时的)write-up关于调度的问题。关于Go调度程序何时创建新的M和P?的答案描述了一些其他特性。

请注意,进程和thread这两个术语已经相当模糊,尽管在区别上有一些普遍的共识。看看进程和thread之间有什么区别吗?goroutine非常像thread,但一般来说,大多数现代的thread系统为每个thread分配一个threadID.Goroutines没有ID,这意味着无法与任何其他goroutine有意义地谈论特定goroutine。这有助于迫使Go程序员使用通道进行通信。(它不能完全强制这样做,但确实有帮助。)。😀)

为了真正演示并行操作,您可以超越Go规范,进入未定义行为的领域不幸的是,由于您已经超出了Go规范,您现在不再首先编写(可移植的)Go程序:您的演示只是演示了有关特定实现的一些内容。

您也可以使用调试器,例如delve。调试器通常必须以各种poorly-defined方式与运行时和操作系统交互,以便能够向您显示程序中正在发生的事情,这样做,它们往往会显示各种not-defined-by-the-specificationbut-actually-works-like-this行为。除非(e.g.提供这些行为,否则您无法得到任何保证)你的操作系统。但你肯定看到了很多东西!