文章引用自

Golang中runtime的使用

runtime调度器是非常有用的东西,关于runtime包几个方法

  • Gosched:让当前线程让出cpu以让其他线程运行,它不会挂起当前线程,因此当前线程未来会继续执行

  • NumCPU:返回当前系统的CPU核数量

  • GOMAXPROCS:设置最大的可同时使用的CPU核数

  • Goexit:退出当前goroutine(但是defer语句会照常执行)

  • NumGoroutine:返回真该执行和排队的任务总数

  • GOOS:目标操作系统

  • GOROOT:返回本机的GO路径
package main

import "fmt"
import "runtime" func main() {
fmt.Println("cpus:", runtime.NumCPU()) // 返回当前系统的CPU核数量
fmt.Println("goroot:", runtime.GOROOT()) //
fmt.Println("NumGoroutine:", runtime.NumGoroutine()) // 返回真该执行和排队的任务总数
fmt.Println("archive:", runtime.GOOS) // 目标操作系统
} 运行结果
cpus: 12
goroot: /usr/local/go
NumGoroutine: 1
archive: darwin

  

GOMAXPROCS

  // 修改最大可同时使用CPU核数

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

package main
import "fmt"
import "runtime"
import "time" func init(){
runtime.GOMAXPROCS(4) // 修改最大可同时使用CPU核数
} func main(){
t := time.Now().Nanosecond()
for i:=0;i<100000;i++{
fmt.Println(i*i*i*i)
}
t2 := time.Now().Nanosecond()
fmt.Println(t2-t)
}

  

Gosched

  // 让当前线程让出cpu以让其他线程运行,它不会挂起当前线程,因此当前线程未来会继续执行

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

package main

import (
"fmt"
"runtime"
) func init() {
runtime.GOMAXPROCS(1) //使用单核
} func main() {
exit := make(chan int)
go func() {
defer close(exit)
go func() {
fmt.Println("b")
}()
}() for i := 0; i < 4; i++ {
fmt.Println("a:", i) if i == 1 {
runtime.Gosched() //切换任务
}
}
<-exit
}

  

在windows系统上,结果为:

    a: 0
a: 1
a: 2
a: 3

  

切换成多核,每次运行的结果都不一样:

package main

import (
"fmt"
"runtime"
) func main() {
runtime.GOMAXPROCS(4)
exit := make(chan int)
go func() {
defer close(exit)
go func() {
fmt.Println("b")
}()
}() for i := 0; i < 10; i++ {
fmt.Println("a:", i) if i == 4 {
runtime.Gosched() //切换任务
}
}
<-exit
}

  

总结:多核比较适合那种CPU密集型程序,如果是IO密集型使用多核会增加CPU切换的成本。

GOMAXPROCS和sync配合使用

sync.WaitGroup只有三个方法,Add(),Done()和Wait()。其中Done()是Add(-1)的别名。简单来说,使用Add()添加计数,Done()减少一个计数,计数不为0,阻塞Wait()的运行。

package main

import (
"runtime"
"sync"
"fmt"
) func main(){
runtime.GOMAXPROCS(2)
var wg sync.WaitGroup
wg.Add(2)
fmt.Printf("Starting go routines")
go func(){
defer wg.Done()
for char := 'a';char<'a'+26;char++{
fmt.Printf("%c",char)
}
}()
go func() {
defer wg.Done()
for number := 1;number<27;number++{
fmt.Printf("%d",number)
}
}() fmt.Println("\nWaiting to finish")
wg.Wait()
fmt.Println("\n terminating program")
}

  

运行结果:

Starting go routines
Waiting to finish
1234567891011121314151617181920212223242526abcdefghijklmnopqrstuvwxyz
terminating program

  

总结:首先是wg.Add(2)计数为2,阻塞wg.Wait()的运行,然后是wg.Done()减少计数到0,放开wg.Wait()的运行。

runtime.Caller

  Caller 方法反应的是堆栈信息中某堆栈帧所在文件的绝对路径和语句所在文件的行数。而 skip 表示的是从下往上数第几个堆栈帧。如果要打印全部堆栈信息可以直接使用 debug.PrintStack() 来实现。

  

  func Caller(skip int) (pc uintptr, file string, line int, ok bool)

  参数:skip是要提升的堆栈帧数,0-当前函数,1-上一层函数,....

  

  返回值:

   pc是uintptr这个返回的是函数指针

  file是函数所在文件名目录

  line所在行号

   ok 是否可以获取到信息

示例:

我们分别打印skip为0-3的相关信息

package main

import (
"fmt"
"runtime"
) func main() {
for i := 0 ; i< 4; i++ {
test(i)
}
} func test(skip int) {
call(skip)
} func call(skip int) {
pc,file,line,ok := runtime.Caller(skip)
pcName := runtime.FuncForPC(pc).Name() //获取函数名
fmt.Println(fmt.Sprintf("%v %s %d %t %s",pc,file,line,ok,pcName))

返回

17412399   /Users/songzhibin/go/src/Songzhibin/study/3.go   19   true   main.call
17412303 /Users/songzhibin/go/src/Songzhibin/study/3.go 15 true main.test
17412294 /Users/songzhibin/go/src/Songzhibin/study/3.go 10 true main.main
16953069 /usr/local/go/src/runtime/proc.go 203 true runtime.main

  

  

最新文章

  1. eclipse启动优化,终于不那么卡了!
  2. uva10106(大数乘法)
  3. HTTP Status 404 - /chp-adapter-web/ 问题解决
  4. 关于把A表中的数据复制到B表中(整理)
  5. php如何支持实现多线程并发
  6. MVC 文件上传
  7. HDU_1401——分步双向BFS,八进制乘权值压缩,map存放hash
  8. FreeCAD源码阅读笔记
  9. javascript中的双向绑定
  10. PHP中的http协议
  11. HT for Web框架使用心得
  12. 客户端与服务器之间通信收不到信息——readLine()
  13. Mongodb Mysql NoSQL的区别和联系
  14. 如何在vue+element中实现选择框和穿梭框的根据拼音以及拼音首字母以及汉字的模糊搜索
  15. 数据库_Redis 入门基础到高级
  16. 内核态与用户态通信 之 sockopt
  17. flask 表单
  18. 2015-09-16 html课程总结1
  19. jmeter中测试接口
  20. [leetcode]304. Range Sum Query 2D - Immutable二维区间求和 - 不变

热门文章

  1. pycharm项目移植过程中遇到的问题
  2. [LOJ113] 最大异或和 - 线性基
  3. Autocorrelation in Time Series Data
  4. git 卡住推不上去
  5. CSS布局的四种定位方式
  6. MySQL认知
  7. 当你工作与生活迷茫时可以来看看 shuke
  8. Spring MVC 中使用properties文件
  9. python面试的100题(5)
  10. 快捷键(一):Win10