Go语言runtime

幸运草 2020年4月15日21:46:32前端框架评论阅读模式

Go语言runtime

runtime包提供Go语言运行时的系统交互的操作,例如控制goruntine的功能。

调度器不能保证多个 goroutine 执行次序,且进程退出时不会等待它们结束。

默认情况下,进程启动后仅允许一个系统线程服务于 goroutine。可使用环境变量或标准库函数 runtime.GOMAXPROCS 修改,让调度器用多个线程实现多核并行,而不仅仅是并发。

runtime包常用方法

const GOOS string = theGoos

GOOS是可执行程序的目标操作系统(将要在该操作系统的机器上执行):darwin、freebsd、linux等。

func Gosched()

Gosched使当前go程放弃处理器,以让其它go程运行。它不会挂起当前go程,因此当前go程未来会恢复执行。

func NumCPU() int

NumCPU返回本地机器的逻辑CPU个数。

func GOROOT() string

GOROOT返回Go的根目录。如果存在GOROOT环境变量,返回该变量的值;否则,返回创建Go时的根目录。

func GOMAXPROCS(n int) int

GOMAXPROCS设置可同时执行的最大CPU数,并返回先前的设置。 若 n < 1,它就不会更改当前设置。本地机器的逻辑CPU数可通过 NumCPU 查询。本函数在调度程序优化后会去掉。

func Goexit()

Goexit终止调用它的go程。其它go程不会受影响。Goexit会在终止该go程前执行所有defer的函数。

在程序的main go程调用本函数,会终结该go程,而不会让main返回。因为main函数没有返回,程序会继续执行其它的go程。如果所有其它go程都退出了,程序就会崩溃。

func NumGoroutine() int

NumGoroutine返回当前存在的Go程数。

runtime包应用

一、查看机器的逻辑CPU个数、Go的根目录、操作系统

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Println("cpus:", runtime.NumCPU())
    fmt.Println("goroot:", runtime.GOROOT())
    fmt.Println("os/platform:", runtime.GOOS)
}

二、GOMAXPROCS 设置golang运行的cpu核数

Golang 默认所有任务都运行在一个 cpu 核里,如果要在 goroutine 中使用多核,可以使用 runtime.GOMAXPROCS 函数修改,当参数小于 1 时使用默认值。

package main

import (
    "fmt"
    "runtime"
)

var (
    signal = false
)

func oldboy() {
    signal = true
}

func init() {
    runtime.GOMAXPROCS(1)
}

func main() {
    go oldboy()
    for {
        if signal {
            break
        }
    }
    fmt.Println("end")
}

上述代码单核执行如果for前面或者中间不延迟,主线程不会让出CPU,导致异步的线程无法执行,从而无法设置signal的值,从而出现死循环。

运行的cpu核数设置成2核

package main

import (
    "fmt"
    "runtime"
)

var (
    signal = false
)

func oldboy() {
    signal = true
}

func init() {
    runtime.GOMAXPROCS(2)
}

func main() {
    go oldboy()
    for {
        if signal {
            break
        }
    }
    fmt.Println("end")
}

运行结果:

end

三、Gosched 让当前的 goroutine 让出 CPU

这个函数的作用是让当前 goroutine 让出 CPU,当一个 goroutine 发生阻塞,Go 会自动地把与该 goroutine 处于同一系统线程的其他 goroutine 转移到另一个系统线程上去,以使这些 goroutine 不阻塞。当前的 goroutine 不会挂起,当前的 goroutine 程未来会恢复执行。

runtime.Gosched()用于让出CPU时间片。这就像跑接力赛,A跑了一会碰到代码runtime.Gosched()就把接力棒交给B了,A歇着了,B继续跑。

package main

import (
    "fmt"
    "runtime"
    "sync"
)

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(1)

    go func() {
        for i := 0; i < 6; i++ {
            fmt.Println(i)
            runtime.Gosched()
        }
        defer wg.Done()
    }()
    for i := 0; i < 6; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            fmt.Println("Hello, Golang!")
        }()
    }

    wg.Wait()
}

四、Goexit 终止当前 goroutine 执行

调用 runtime.Goexit 将立即终止当前 goroutine 执行,调度器确保所有已注册 defer 延迟调用被执行。

package main

import (
    "fmt"
    "runtime"
    "sync"
)

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(1)

    go func() {
        defer wg.Done()
        defer fmt.Println("A.defer")
        func() {
            defer fmt.Println("B.defer")
            runtime.Goexit() // 终止当前 goroutine
            fmt.Println("B") // 不会执行
        }()

        fmt.Println("A") // 不会执行
    }()

    wg.Wait()
}

运行结果:

B.defer
A.defer

特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

  • 赞助本站
  • 微信扫一扫
  • weinxin
  • 加入Q群
  • QQ扫一扫
  • weinxin
幸运草
Go语言接口规则 前端框架

Go语言接口规则

Go语言接口规则 接口是一个或多个方法签名的集合。任何类型的方法集中只要拥有该接口对应的全部方法签名。就表示它 "实现" 了该接口,无须在该类型上显式声明实现了哪个接口。对应方法,是指有相同名称、参数...
Go语言中处理 HTTP 服务器 前端框架

Go语言中处理 HTTP 服务器

1 概述 包 net/http 提供了HTTP服务器端和客户端的实现。本文说明关于服务器端的部分。 快速开始: package main import (   "log"   "net/http" )...

发表评论