channel
parent
3477d7143d
commit
dd9b607ebe
|
@ -1,28 +0,0 @@
|
||||||
并发的介绍
|
|
||||||
golang是天然支持高并发的语言
|
|
||||||
并发:同一时间内执行多个任务
|
|
||||||
并行:同一时刻执行多个任务
|
|
||||||
|
|
||||||
golang的并发通过goroutine实现,goroutine是用户态的线程,由go的运行时runtime调度,而线程是通过操作系统去调度。
|
|
||||||
最终还是放在操作系统的线程去执行,只不过管理(上下文切换)放在用户态,所以开销较小。
|
|
||||||
|
|
||||||
golang提供channel用来在多个goroutine之间进行通信。
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
只需要在调用函数前加上 go 关键字 即可开启一个goroutine
|
|
||||||
|
|
||||||
|
|
||||||
goroutine对应的函数执行结束了,goroutine就结束了
|
|
||||||
main函数执行完毕,由main函数创建的那些goroutine就结束了
|
|
||||||
|
|
||||||
如何等待所有的goroutine结束之后再执行主函数?
|
|
||||||
sync.waitGroup对象中有三个方法
|
|
||||||
var wg sync.waitGroup
|
|
||||||
wg.add(1) //计数器加1
|
|
||||||
wg.done()//计数器减1
|
|
||||||
wg.wait()//等待所有的goroutine结束
|
|
||||||
|
|
||||||
|
|
||||||
goroutine与线程
|
|
||||||
os线程有固定的栈内存
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 通道的声明
|
||||||
|
var c chan int //需要指定通道中元素的类型,引用类型,需要初始化
|
||||||
|
var wait sync.WaitGroup
|
||||||
|
|
||||||
|
func noBufferedChannel() {
|
||||||
|
c = make(chan int) //不带带缓冲区的通道初始化
|
||||||
|
wait.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wait.Done()
|
||||||
|
x := <-c //接受
|
||||||
|
fmt.Println("从通道C中取得值:", x)
|
||||||
|
}()
|
||||||
|
c <- 10 //发送
|
||||||
|
wait.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func bufferedChannel() {
|
||||||
|
c = make(chan int, 1) //带缓冲区的初始化
|
||||||
|
c <- 10
|
||||||
|
fmt.Println("10发送到通道中了")
|
||||||
|
x := <-c
|
||||||
|
fmt.Println("从通道C中取到值", x)
|
||||||
|
c <- 20
|
||||||
|
fmt.Println("20发送到通道中了")
|
||||||
|
z := <-c
|
||||||
|
fmt.Println("从通道C中取到值", z)
|
||||||
|
close(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bufferedChannel()
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
并发的介绍
|
||||||
|
golang是天然支持高并发的语言
|
||||||
|
并发:同一时间内执行多个任务
|
||||||
|
并行:同一时刻执行多个任务
|
||||||
|
|
||||||
|
golang的并发通过goroutine实现,goroutine是用户态的线程,由go的运行时runtime调度,而线程是通过操作系统去调度。
|
||||||
|
最终还是放在操作系统的线程去执行,只不过管理(上下文切换)放在用户态,所以开销较小。
|
||||||
|
|
||||||
|
golang提供channel用来在多个goroutine之间进行通信。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
只需要在调用函数前加上 go 关键字 即可开启一个goroutine
|
||||||
|
|
||||||
|
goroutine什么时候结束?
|
||||||
|
|
||||||
|
goroutine对应的函数执行结束了,goroutine就结束了
|
||||||
|
main函数执行完毕,由main函数创建的那些goroutine就结束了
|
||||||
|
|
||||||
|
如何等待所有的goroutine结束之后再执行主函数?
|
||||||
|
sync.waitGroup对象中有三个方法
|
||||||
|
var wg sync.waitGroup
|
||||||
|
wg.add(1) //计数器加1
|
||||||
|
wg.done()//计数器减1
|
||||||
|
wg.wait()//等待所有的goroutine结束
|
||||||
|
|
||||||
|
|
||||||
|
goroutine与线程
|
||||||
|
os线程有固定的栈内存。一般是2MB,一个goroutine的生命周期开始的时候占用的内存是2kb
|
||||||
|
goroutine的栈内存不是固定的,可以按需扩大或者缩小,最大1Gb
|
||||||
|
|
||||||
|
|
||||||
|
goroutine的调度
|
||||||
|
G: 即goroutine,里面除了存放本goroutine的信息之外还有与所在的p的绑定等信息。
|
||||||
|
M: machine是go运行时对操作系统线程内核线程的虚拟,M与内核线程一般是一一映射的关系,一个goroutine最终是要放到M上
|
||||||
|
去运行的。
|
||||||
|
P: P管理着一组goroutine队列,P里面会存储当前goroutine运行的上下文环境(函数指针,堆栈地址,以及地址边界),P会对自己管理的goroutine队列做一些调度
|
||||||
|
当自己的队列消费完成之后就去全局队列里面取,如果全局队列里也消费完了回去其他P的队列里抢任务。
|
||||||
|
|
||||||
|
|
||||||
|
P和M一般也是一一对应的,他们的关系是:P管理着一组G挂载在M上运行,当一个G长久阻塞在一个M上时,runtime会新建一个M,阻塞G所在的P会把其他的G挂载在新的M上,
|
||||||
|
当旧的G阻塞完成或者认为其已经死掉时,回收旧的M。
|
||||||
|
|
||||||
|
|
||||||
|
P的个数通过runtime.GOMAXPROC指定,最大256,GO1.5版本后默认为物理线程数,在并发量大的时候最增加一些P和M,但不会太多
|
||||||
|
|
||||||
|
M:N 复用/调度M的goroutine的到N个os线程
|
||||||
|
|
||||||
|
|
||||||
|
一个操作系统的线程对应多个用户态的goroutine
|
||||||
|
狗程序可以同时使用多个操作系统线程
|
||||||
|
goroutine和os线程时多对多的关系,即M:N
|
|
@ -0,0 +1,31 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var wgGroup sync.WaitGroup
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
runtime.GOMAXPROCS(2) //指定P的数量
|
||||||
|
wgGroup.Add(2)
|
||||||
|
go a()
|
||||||
|
go b()
|
||||||
|
wgGroup.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func a() {
|
||||||
|
defer wgGroup.Done()
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
fmt.Printf("A:%v\n", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func b() {
|
||||||
|
defer wgGroup.Done()
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
fmt.Printf("B:%v\n", i)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue