建立一个goroutine大概2KB的栈空间,新建立的线程会占用1MB的内存空间。并发
线程须要从操做系统里请求资源并在用完以后释放回去,所以建立和销毁线程的开销很是大。
goroutine的建立和销毁是由运行环境(runtime)完成的,这些操做的开销就比较小。函数
当切换一个线程的时候,调度器须要保存/恢复全部的寄存器。这包括16个通用寄存器,程序指针(program counter),栈指针(stack pointer),段寄存器(segment registers)和16个XMM寄存器,浮点协处理器状态,16个AVX寄存器,全部的特殊模块寄存器(MSR)等。当在线程间快速切换的时候这些开销就变得很是大了
Goroutine的调度是协同合做式的(cooperatively)。当切换goroutine的时候,调度器只须要保存和恢复三个寄存器 - 程序指针,栈指针和DX。切换的开销就小多了。oop
并行:是让不一样的代码片断同时在不一样的物理处理器上执行,并行的关键是同时作不少事情。
并发:指同时管理不少事情,这些事情可能只作了一半就被暂停去作别的事情了,goroutine是一种并发机制。操作系统
package main import "fmt" func main() { var i = 3 go func(a int) { fmt.Println(a) fmt.Println("1") }(i) fmt.Println("2") }
package main import ( "runtime" "sync" "fmt" ) func main() { // 分配一个逻辑处理器给调度器使用 runtime.GOMAXPROCS(1) // wg用来等待程序完成,计数加2,表示要等待两个goroutine var wg sync.WaitGroup wg.Add(2) fmt.Println("Start Goroutines") // 声明一个匿名函数,并建立一个goroutine go func() { // 延时调用,在函数退出时调用done来通知main函数工做已经完成 defer wg.Done() // 显示字母表三次 for count := 0; count < 3; count ++ { for char := 'a'; char < 'a' + 26 ; char ++ { fmt.Printf("%c ", char) } } }() go func() { defer wg.Done() for count := 0; count < 3; count ++ { for char := 'A'; char < 'A' + 26 ; char ++ { //time.Sleep(time.Millisecond) fmt.Printf("%c ", char) } } }() fmt.Println("Wating To Finish") wg.Wait() fmt.Println("\nTerminating Program") }