Goroutine&channel
Goroutine基本介绍 进程和线程说明
进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位#线程是进程的一个执行实例,是程序执行的最小单元,它是比进程更小的能独立运行的基本单位
#一个进程可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行 #一个程序至少有一个进程,一个进程至少有一个线程 并发和并行 并发:多线程程序在单核上运行 并行:多线程程序在多核上运行 Go协程和go主线程
go主线程:一个go线程上,可以起多个协程# go协程的特点: *有独立的栈空间 *共享程序堆空间 *调度由用户控制 *协程是轻量级的线程代码实例:import(
"fmt"
"strconv"
"time"
)
functest() {
fori :=0;i <10;i++ {
fmt.Println("hello world~"+strconv.Itoa(i)) time.Sleep(time.Second)
}
}
funcmain() {
gotest()
fori :=0;i <10;i++ {
fmt.Println("hello goland~"+strconv.Itoa(i)) time.Sleep(time.Second) }
}
说明:
#如果主线程退出了,则协程即使没有执行完毕也会退出#协程也可以在主线程没有退出前就自动结束
小结:
#主线程是一个物理线程,直接作用在cpu上,是重量级的,非常耗费cpu资源#协程从主线程开始的,是轻量级的线程,是逻辑态,对资源消耗相对小
golang的协程机制是重要特点,可以轻松开启上万个协程,其他编程语言的并发机制是一般基于线程的,开启过多的线程,资源耗费大(MPG模式基本介绍M:操作系统的主线程P:协程执行需要的上下文G:协程)
管道介绍
channel本质就是一个数据结构——队列#数据是先进先出#线程安全,多goroutine访问时,不需要加锁,就是说channel本身就是线程安全的
channel有类型的,一个string的channel只能存放string数据类型定义声明Var变量名chan数据类型举例:Var intChan chan int
Var mapChan chan map[int]string Var perChan chan Person…… 说明:
channel是引用类型
channel必须初始化才能写入数据,即make后才能使用#管道是有类型的,intChan只能写入整数int
注意事项:
channel中只能存放指定数据类型
channel的数据放满后,就不能再放入了#如果从channel取出数据后,可以继续放入
#在没有使用协程的情况下,如果channel数据被取完了,再取就会报dead lock channel的关闭 使用内置函数close()可以关闭channel,当channel关闭后,就不能再向channel写数据了,但是仍然可以从该channel中读取数据。 Channel的遍历 channel支持for_range的方式进行遍历,请注意以下两个细节: #在遍历时,如果channel没有关闭,则会出现deadlock的错误 #在遍历时,如果channel已经关闭,则会正常遍历数据,遍历完后,就会退出遍历 注意事项:
channel可以声明为只读或者只写 #使用select可以解决从管道读取数据的阻塞问题
goroutine中使用recover,解决协程中出现panic,导致程序崩��问题说明:如果我们起了一个协程,但是这个协程出现了panic,如果我们没有捕获这个panic,就会造成整个程序崩溃,这时我们可以在goroutine中使用recover来捕获panic进行处理,这样即时这个协程发生的问题,但是线程仍然不受影响,可以继续执行
心得体会:go管道并发简单易用高效易于扩展,竞争少,可以使代码更简洁,提高代码可重用性。go语言的管道并发相比于传统的多线程编程更加简单高效和安全,在编写并发程序时是一个不错的选择。