首页>>后端>>Golang->Golang中什么时候用Goroutine?什么时候用Channel?

Golang中什么时候用Goroutine?什么时候用Channel?

时间:2023-11-29 本站 点击:0

什么场景下用channel合适呢?

通过全局变量加锁同步来实现通讯,并不利于多个协程对全局变量的读写操作。

加锁虽然可以解决goroutine对全局变量的抢占资源问题,但是影响性能,违背了原则。

总结:为了解决上述的问题,我们可以引入channel,使用channel进行协程goroutine间的通信。

Go语言中的操作系统线程和goroutine的关系:

一个操作系统线程对应用户态多个goroutine。

go程序可以同时使用多个操作系统线程。

goroutine和OS线程是多对多的关系,即m:n。

Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信,引出了channel。

通道channel使用示例:

for range 从通道中取值,通道关闭时for range 退出

//channel练习goforrange从chan中取值ch1:=make(chanint)ch2:=make(chanint)//开启goroutine把0-100写入到ch1通道中gofunc(){fori:=0;i<100;i++{ch1<-i}close(ch1)}()//开启goroutine从ch1中取值,值的平方赋值给ch2gofunc(){for{i,ok:=<-ch1//通道取值后再取值ok=falseifok{ch2<-i*i}else{break}}close(ch2)}()//主goroutine从ch2中取值打印输出//forx:=chan有值取值,通道关闭时跳出goroutinefori:=rangech2{fmt.Println(i)}

channel升级,单通道,只读通道和只写通道

funccounter(inchan<-int){deferclose(in)fori:=0;i<100;i++{in<-i}}funcsquare(inchan<-int,out<-chanint){deferclose(in)fori:=rangeout{in<-i*i}}funcoutput(out<-chanint){fori:=rangeout{fmt.Println(i)}}//改写成单向通道funcmain(){ch1:=make(chanint)ch2:=make(chanint)gocounter(ch1)gosquare(ch2,ch1)output(ch2)}

goroutine work pool,可以防止goroutine暴涨或者泄露

//使用workpool防止goroutine的泄露和暴涨funcworker(idint,jobs<-chanint,resultschan<-int){forj:=rangejobs{fmt.Printf("worker:%dstartjob:%d\n",id,j)time.Sleep(time.Second)fmt.Printf("worker:%dendjob:%d\n",id,j)results<-j*2}}funcmain(){jobs:=make(chanint,100)results:=make(chanint,100)//开启3个goroutineforw:=1;w<=3;w++{goworker(w,jobs,results)}//5个任务forj:=1;j<=5;j++{jobs<-j}close(jobs)//输出结果fora:=1;a<=5;a++{<-results}}

goroutine使用select case多路复用,满足我们同时从多个通道接收值的需求

//使用select语句能提高代码的可读性。//可处理一个或多个channel的发送/接收操作。//如果多个case同时满足,select会随机选择一个。//对于没有case的select{}会一直等待,可用于阻塞main函数。ch:=make(chanint,1)gofunc(){fori:=0;i<10;i++{select{casex:=<-ch:fmt.Println(x)casech<-i:}}}()

goroutine加锁 排它锁 读写锁

varxint64varwgsync.WaitGroup//添加互斥锁varlocksync.Mutexfuncmain(){wg.Add(2)goadd()goadd()wg.Wait()fmt.Println(x)}funcadd(){fori:=0;i<5000;i++{lock.Lock()//加锁x=x+1lock.Unlock()//解锁}wg.Done()}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Golang/238.html