进程和线程说明:
(1)进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位。
(2)线程是进程的一个执行实例,是程序执行的最小单位,它是比进程更小的能独立运行的基本单位。
(3)一个进程可以创建销毁多个线程,同一个进程中的多个线程可以并发执行。
(4)一个程序至少有一个进程,一个进程至少有一个线程。
并发和并行:
(1)多线程程序在单核上运行就是并发。
(2)多线程程序在多核上运行就是并行。
Go协程和Go主线程:
(1)Go主线程:一个Go线程上可以起多个协程,协程是轻量级线程;
(2)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:///0voice/Introduction-to-Golang
Go中文网链接:https:///
Golang标准文档:https:///pkgdoc