速戰速決 go - go 高級: 多線程和線程同步 goroutine

速戰速決 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章