go语言--goroutine

1、goroutine

  • goroutine就是Go语言提供的一种用户态线程。Go本身实现了goroutine的调度器(Scheduler),Go的调度器由三部分组成:
  • M:指的是Machine,一个M直接关联了一个内核线程。
  • P:指的processer,表明M所需的上下文环境,也是处理用户级代码逻辑的处理器。P的数量能够经过GOMAXPROCS()来设置,默认值是CPU的核数。
  • G:指的是goroutine,其实本质上也是一种轻量级的线程。

2、goroutine和线程的区别

一、内存占用

建立一个goroutine大概2KB的栈空间,新建立的线程会占用1MB的内存空间。并发

二、建立和销毁的开销

线程须要从操做系统里请求资源并在用完以后释放回去,所以建立和销毁线程的开销很是大。
goroutine的建立和销毁是由运行环境(runtime)完成的,这些操做的开销就比较小。函数

三、切换开销

当切换一个线程的时候,调度器须要保存/恢复全部的寄存器。这包括16个通用寄存器,程序指针(program counter),栈指针(stack pointer),段寄存器(segment registers)和16个XMM寄存器,浮点协处理器状态,16个AVX寄存器,全部的特殊模块寄存器(MSR)等。当在线程间快速切换的时候这些开销就变得很是大了
Goroutine的调度是协同合做式的(cooperatively)。当切换goroutine的时候,调度器只须要保存和恢复三个寄存器 - 程序指针,栈指针和DX。切换的开销就小多了。oop

3、goroutine执行过程

4、goroutine并发

并行:是让不一样的代码片断同时在不一样的物理处理器上执行,并行的关键是同时作不少事情。
并发:指同时管理不少事情,这些事情可能只作了一半就被暂停去作别的事情了,goroutine是一种并发机制。操作系统

5、goroutine代码示例

  • 下面例子只会输出2,不会输出 1 3,由于当程序优先执行主线程,当主线程执行完后就退出了。
package main

import "fmt"

func main() {

    var i = 3

    go func(a int) {
        fmt.Println(a)
        fmt.Println("1")
    }(i)

    fmt.Println("2")
}
  • 这个例子是分部打印三次大小写字母,你们能够把runtime.GOMAXPROCS(2)或者time.Sleep(time.Millisecond)注释取消掉,再看下运行结果,每次输出都不同有助于进一步理解goroutine。
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")
}
相关文章
相关标签/搜索