本文主要是介绍4-golang协程(goroutine)和管道(channel),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
4-golang协程(goroutine)和管道(channel)
1. 并发和并行
多线程程序在单核上运行,就是并发
多线程程序在多核上运行,就是并行
2. go协程和线程
- Go主线程(也可以称为线程,可以理解为进程):一个Go线程上可以起多个协程,协程是轻量级的线程
- Go协程的特点
- 有独立的栈空间
- 共享程序堆空间
- 调度由用户控制
- 协程是轻量级的线程
func test() {for i := 0; i < 10; i++ {fmt.Println("test() hello world " + strconv.Itoa(i))time.Sleep(time.Second)}
}func main() {go test() // 开启了一个协程for i := 0; i < 10; i++ {fmt.Println("main() hello golang " + strconv.Itoa(i))time.Sleep(time.Second)}
}
- 如果主线程退出了,则协程及时还没有执行完毕,也会退出
- 写成也可以在主线程没有退出前就自己结束了,比如完成了自己的任务
3. goroutine的调度模型–MPG模式
M:操作系统的主线程(是物理线程)
P:协程执行需要的上下文
G:协程
4. 管道(Channel)
- channel是一个数据结构,遵循先进先出
- 多goroutine访问时,不需要加锁,channel是线程安全的
- 一个channel中的数据,数据类型要一致。(一个string的channel,只能存放string数据类型)
- channel需要make后使用,make时需要设置channel长度
- channel数据放满后,再放数据会报错,取出数据后,可以再放数据
- 在没有协程的情况下,channel数据取完后,再取数据会报错
- 使用内置的 close(channelName) 可以关闭channel,此时不能再向channel写数据,但是可以读数据
- 遍历channel使用for-range遍历。在遍历时,如果channel没有关闭,则会报错;如果channel已经关闭,会再遍历完成后退出遍历。(遍历不要使用普通for,因为在取出channel数据后,channel长度会改变)
package mainimport "fmt"// write data
func writeData(intChan chan int) {for i := 1; i <= 1000; i++ {// 放入数据intChan <- ifmt.Printf("writeData 写入数据=%v\n", i)}// 写完后关闭close(intChan)
}func readChain(intChan chan int, exitChan chan bool) {for {v, ok := <-intChanif !ok {break}fmt.Printf("readData 读到数据=%v\n", v)}// 读完数据后,任务完成exitChan <- trueclose(exitChan)
}func main() {// 创建两个管道intChan := make(chan int, 1000)exitChan := make(chan bool, 1)go writeData(intChan)go readChain(intChan, exitChan)for {_, ok := <-exitChanif !ok {break}}}
这篇关于4-golang协程(goroutine)和管道(channel)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!