速戰速決 go https://github.com/webabcd/GoSample
作者 webabcd
速戰速決 go - go 高級: 多線程和線程同步 goroutine
示例如下:
advanced/goroutine1.go
// go 高級 - 多線程和線程同步 goroutine
// 併發(concurrency)- 在某個 cpu 核心上多線程
// 並行(parallelism)- 在多個 cpu 核心上多線程(go 的多線程就是並行的,它會最大效率利用多核 cpu)
// goroutine 相當於輕量級的線程(相對於傳統線程來說效率要高出很多),通過 go 關鍵字創建 goroutine,通過 channel 做 goroutine 間的通信
package advanced
import (
"fmt"
"runtime"
"sync"
"time"
)
var (
// 在多線程場景下設置此值
count int
// sync.Mutex - 互斥鎖
// sync.RWMutex - 讀寫互斥鎖(讀鎖佔用,則阻止寫不阻止讀;寫鎖佔用,則阻止讀寫)
// Lock() - 加鎖
// Unlock() - 解鎖
lock sync.Mutex
// sync.WaitGroup - 等待組(維護一個計數器,用於管理阻塞)
// Add(delta int) - 計數器加上指定的值
// Done() - 計數器減 1
// Wait() - 阻塞,等計數器等於 0 後停止阻塞
wg sync.WaitGroup
)
func Goroutine1Sample() {
// 獲取 cpu 的核心數
fmt.Println("NumCPU", runtime.NumCPU())
// 設置程序可以用到的最大 cpu 核心數(go 會最大效率利用多核 cpu,這裏的默認值就是全部 cpu 核心)
runtime.GOMAXPROCS(runtime.NumCPU())
// 等待組計數器 +11
wg.Add(11)
for i := 0; i < 10; i++ {
// go - 讓指定的函數在新的 goroutine 運行
go running()
}
// go - 讓指定的匿名函數在新的 goroutine 運行
go func() {
// 等待組計數器 -1
defer wg.Done()
// 當前線程睡 100 毫秒
time.Sleep(time.Millisecond * 100) // 單位是納秒
for {
plusOne()
if count > 100 {
break
}
}
}()
// 阻塞,直到等待組計數器等於 0 後停止阻塞
wg.Wait()
fmt.Println("結束")
}
func running() {
// 等待組計數器 -1
defer wg.Done()
// 當前線程睡 100 毫秒
time.Sleep(time.Millisecond * 100) // 單位是納秒
for {
plusOne()
if count > 100 {
break
}
}
}
// count 變量加 1,並打印當前 count 的值
// 這個函數用於演示多線程場景下的線程同步,如果不加鎖的話輸出就亂七八糟,如果加鎖的話則輸出符合預期
func plusOne() {
// 解鎖
defer lock.Unlock()
// 加鎖
lock.Lock()
count++
fmt.Println("count", count)
}
速戰速決 go https://github.com/webabcd/GoSample
作者 webabcd