速战速决 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

posted @ 2022-02-08 14:33  webabcd  阅读(20)  评论(0编辑  收藏  举报