Go-goroutine
Goroutine基本介绍
进程和线程说明:
(1)进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位。
(2)线程是进程的一个执行实例,是程序执行的最小单位,它是比进程更小的能独立运行的基本单位。
(3)一个进程可以创建销毁多个线程,同一个进程中的多个线程可以并发执行。
(4)一个程序至少有一个进程,一个进程至少有一个线程。
并发和并行:
(1)多线程程序在单核上运行就是并发。
(2)多线程程序在多核上运行就是并行。
Go协程和Go主线程:
(1)Go主线程:一个Go线程上可以起多个协程,协程是轻量级线程;
(2)Go协程的特点:
- 有独立的栈空间
- 共享程序堆空间
- 调度由用户控制
- 协程是轻量级线程
Go实例
简单实例:
package main
import (
"fmt"
"time"
)
func test() {
for i := 0; i < 10; i++ {
fmt.Println("test", "Hello world", i)
time.Sleep(time.Second)
}
}
func main() {
// 开启goroutine
go test()
for i := 0; i < 10; i++ {
fmt.Println("main", "Hello golang", i)
time.Sleep(time.Second)
}
}
设置CPU使用个数:
package main
import (
"fmt"
"runtime"
)
func main() {
// CPU个数
num := runtime.NumCPU()
// 设置使用的CPU个数
runtime.GOMAXPROCS(num)
fmt.Println(num)
}
资源竞争问题:
在运行某程序时,如何知道是否存在资源竞争问题?
go build -race test.go
资源竞争问题:
package main
import (
"fmt"
"time"
)
/*
需求:计算1-200各个数的阶乘,并且把各个数的阶乘放到map中。最后显示出来。
问题:会出现并发/并行安全问题(Found 2 data race(s))
*/
var (
myMap = make(map[int]int, 10)
)
// 计算n的阶乘,将结果放入到map中
func test(n int) {
res := 1
for i := 1; i <= n; i++ {
res *= i
}
// fatal error: concurrent map writes
myMap[n] = res
}
func main() {
for i := 1; i <= 200; i++ {
go test(i)
}
// 设置休眠时间要多长?
time.Sleep(time.Second * 10)
for i, v := range myMap {
fmt.Printf("map[%d]=%d\n", i, v)
}
}
解决方法:使用互斥锁mutex
package main
import (
"fmt"
"time"
"sync"
)
/*
需求:计算1-200各个数的阶乘,并且把各个数的阶乘放到map中。最后显示出来。
问题:会出现并发/并行安全问题(Found 2 data race(s))
解决方法:使用互斥锁,因为阶乘容易越界,所以改成sum += uint64(i)
*/
var (
myMap = make(map[int]int, 10)
// 定义一个全局互斥锁
lock sync.Mutex
)
// 计算n的阶乘,将结果放入到map中
func test(n int) {
res := 0
for i := 1; i <= n; i++ {
res += i
}
// 加锁
lock.Lock()
myMap[n] = res
// 解锁
lock.Unlock()
}
func main() {
for i := 1; i <= 200; i++ {
go test(i)
}
// 设置休眠时间要多长?
time.Sleep(time.Second * 10)
// 加互斥锁的原因:
// 按理来说10s内上述的协程都应该执行完了,后面就不会出现资源竞争的问题
// 但是实际上还是有可能出现竞争问题
// 我们的程序从设计上可以知道10s内执行完所有协程,但是主线程并不知道
// 因此底层还是可能出现资源争夺,所以还是需要加入互斥锁
// 加锁
lock.Lock()
for i, v := range myMap {
fmt.Printf("map[%d]=%d\n", i, v)
}
// 解锁
lock.Unlock()
}
参考资料大全
Go资料大全:https://github.com/0voice/Introduction-to-Golang
Go中文网链接:https://studygolang.com/
Golang标准文档:https://studygolang.com/pkgdoc
浙公网安备 33010602011771号