Golang 并发
- 并行 指的是在同一时刻 有多条指令在多个CPU处理器上同时执行 2个任务2个窗口需要硬件支持
- 并发是指在同一时刻 只能有一条指令 单多个进程指令快速轮换执行 2个队伍1个窗口 要求提升软件能力
Golang 并发优势
Goroutine 是什么
- 它是go 并发设计的核心
- goroutine就是协程,它比线程更小,十几个goroutine 在底层可能就是五六个线程
- go 语言内部实现了goroutine的内存共享,执行goroutine只需极少的栈内存(大概4-5KB)
创建goroutine
- package main
- import (
- "fmt"
- "time"
- )
- //测试协程
- //循环打印内容
- func newTask() {
- i := 0
- for {
- i++
- fmt.Printf("new goroutine\:i=%d\n", i)
- time.Sleep(1 \* time.Second)
- }
- }
- //main()相当于是主协程
- func main() {
- //启动子协程
- go newTask()
- i := 0
- for {
- i++
- fmt.Printf("main goroutine\:i=%d\n", i)
- time.Sleep(1 \* time.Second)
- }
- }
复制代码
- 开发人员无需了解任何执行细节,调度器会自动将其安排到合适的系统线程上运行
- 如果主协程推出,所有子进程协程都会退出
- package main
- import (
- "fmt"
- "time"
- )
- //main()相当于是主协程
- func main() {
- //匿名子协程
- go func() {
- i := 0
- for {
- i++
- fmt.Println("子协程 i=", i)
- time.Sleep(1 \* time.Second)
- }
- }()
- i := 0
- for {
- i++
- fmt.Println("主协程 i=", i)
- time.Sleep(1 \* time.Second)
- //主协程第二次后退出
- if i == 2 {
- break
- }
- }
- }
复制代码- package main
- import (
- "fmt"
- "time"
- )
- //main()相当于是主协程
- func main() {
- //匿名子协程
- go func() {
- i := 0
- for {
- i++
- fmt.Println("子协程 i=", i)
- time.Sleep(1 \* time.Second)
- }
- }()
- }
复制代码 runtime 包
- runtime.Gosched(): 用于让出CPU时间片,调度器重新安排任务调度,还是有几率分配到它的
- package main
- import (
- "fmt"
- "runtime"
- )
- func main() {
- //匿名子协程
- go func(s string) {
- for i := 0; i < 2; i++ {
- fmt.Println(s)
- }
- }("world")
- //主协程
- for i := 0; i < 2; i++ {
- runtime.Gosched()
- fmt.Println("hello")
- }
- }
复制代码
- runtime.Goexit() 立即终止当前协程
- package main
- import (
- "fmt"
- "time"
- "runtime"
- )
- func main() {
- //匿名子协程
- go func() {
- defer fmt.Println("A.defer")
- //匿名函数
- func() {
- defer fmt.Println("B.defer")
- //此时只有defer执行
- runtime.Goexit()
- fmt.Println("B")
- }()
- fmt.Println("A")
- }()
- for {
- time.Sleep(time.Second)
- }
- }
复制代码
- runtime.GOMAXPROCS(): 设置并行计算的CPU核数,返回之前的值
- package main
- import (
- "runtime"
- "fmt"
- )
- func main() {
- n := runtime.GOMAXPROCS(3)
- fmt.Println("n=%d\n",n)
- //循环执行2个
- for{
- go fmt.Print(0)
- fmt.Print(1)
- }
- }
复制代码 channel
- goroutine运行在相同的地址空间,因此访问共享内存必须做好同步,处理好线程安全
- goroutine奉行通过通信来共享内存,而不是共享内存通信
- channel 是一个引用类型 用于多个goroutine 通讯 其内部实现了同步,确保并发安全
Channel 基本使用
<ul>Channel 可以用内置make() 创建
定义一个channel 也需要定义发送到channel值类型
make(chan 类型) // 无缓冲通道
make(chan 类型, 容量) // 有缓冲通道当capacity=0 时, channel 是无缓冲阻塞读写的,当capacity>0, channel 有缓冲,是非阻塞的,直到写满capacity个元素才阻塞写入
channel 通过操作符 |