sync包
sync.Mutex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package main
import ( "fmt" "sync" "time" )
var ( mutex sync.Mutex shared_data int )
func Add1() { for i := 0; i < 1000; i++ { mutex.Lock() shared_data++ mutex.Unlock() } }
func Add2() { for i := 0; i < 1000; i++ { mutex.Lock() shared_data++ mutex.Unlock() } } func main() { go Add1() go Add2() time.Sleep(1 * time.Second) fmt.Println(shared_data) }
|
sync.RWMutex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package main
import ( "fmt" "sync" "time" )
var ( mutex sync.RWMutex shared_data int )
func Add1() { for i := 0; i < 1000; i++ { mutex.Lock() shared_data++ mutex.Unlock() } }
func Add2() { for i := 0; i < 1000; i++ { mutex.Lock() shared_data++ mutex.Unlock() } } func main() { go Add1() go Add2() time.Sleep(1 * time.Second) fmt.Println(shared_data) }
|
sync.WaitGroup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package main
import ( "fmt" "net/http" "sync" )
func main() { var wg sync.WaitGroup var urls = []string{ "http://www.baidu.com/", "https://www.mi.com/", "https://pkg.go.dev/", } for _, url := range urls { wg.Add(1) go func(url string) { defer wg.Done() _, err := http.Get(url) fmt.Println(url, err) }(url) } wg.Wait() fmt.Println("over") }
|
runtime
Go 语言的 goroutine 是由 运行时(runtime)调度和管理的。它负责管理包括内存分配、垃圾回收、
栈处理、goroutine、channel、切片(slice)、map 和反射(reflection)等等。
runtime.Gosched()
让出当前协程的 CPU 时间片给其他协程。当前协程等待时间片未来继续执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package main import ( "fmt" "runtime" ) func main() { go func(s string) { for i := 0; i < 2; i++ { fmt.Println(s) } }("world") for i := 0; i < 2; i++ { runtime.Gosched() fmt.Println("hello") } } #结果 world world hello hello
|
runtime.Goexit()
退出当前协程,但是 defer 语句会照常执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package main
import ( "fmt" "runtime" "time" )
func main() { go func() { defer fmt.Println("A.defer") func() { defer fmt.Println("B.defer") runtime.Goexit() defer fmt.Println("C.defer") fmt.Println("B") }() fmt.Println("A") }() time.Sleep(time.Second) fmt.Println("main") } #结果 B.defer A.defer main
|
runtime.GOMAXPROCS()
Golang 默认所有任务都运行在一个 cpu 核里,如果要在 goroutine 中使用多核,可以使用runtime.GOMAXPROCS 函数修改,当参数小于 1 时使用默认值。
Go运行时的调度器使用 GOMAXPROCS 参数来指定需要使用多少个 OS 线程来同时执行 Go 代码。默认值是机器上的 CPU 核心数。例如在一个 8 核心的机器上,调度器会把 Go 代码同时调度到 8 个 OS 线程上( GOMAXPROCS 是m:n调度中的n)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package main
import ( "fmt" "runtime" "time" )
func a() { for i := 1; i < 10; i++ { fmt.Println("A:", i) } } func b() { for i := 1; i < 10; i++ { fmt.Println("B:", i)
} } func main() { runtime.GOMAXPROCS(runtime.NumCPU()) go a() go b() time.Sleep(time.Second * 2) fmt.Println("over") }
|
runtime.NumCPU()
返回当前系统的 CPU 核数量。
runtime.GOROOT()
获取 goroot 目录。
runtime.GOOS
查看目标操作系统。
runtime.GC
会让运行时系统进行一次强制性的垃圾收集。
强制的垃圾回收:不管怎样,都要进行的垃圾回收。非强制的垃圾回收:只会在一定条件下进行的垃圾回收(即运行时,系统自上次垃圾回收之后新申请的堆内存的单元(也成为单元增量)达到指定的数值)。
runtime.LockOSThread , runtime.UnlockOSThread
runtime.LockOSThread调用会使调用他的 Goroutine 与当前运行它的M锁定到一起。
runtime.UnlockOSThread调用会解除这样的锁定。
runtime.NumGoroutine
返回正在执行和排队的任务总数。
runtime.NumGoroutine函数在被调用后,会返回系统中的处于特定状态的 Goroutine 的数量。这里的特定状态是指Grunnable\Gruning\Gsyscall\Gwaition。处于这些状态的Groutine即被看做是活跃的或者说正在被调度。
注意:垃圾回收所在Groutine的状态也处于这个范围内的话,也会被纳入该计数器。