当前位置: 首页 > news >正文

微信微网站建设平台网站数据统计工具

微信微网站建设平台,网站数据统计工具,北京土巴兔装修公司电话,石碣网站建设目录: (1)Go开发指南-Hello World (2)Go开发指南-Gin与Web开发 (3)Go开发指南-Goroutine Goroutine 在java中我们要实现并发编程的时候,通常要自己维护一个线程池,并且需要去包装任务、调度任务和维护上下文切换。这个过程需要消耗大量的精…

目录:
(1)Go开发指南-Hello World
(2)Go开发指南-Gin与Web开发
(3)Go开发指南-Goroutine

Goroutine

在java中我们要实现并发编程的时候,通常要自己维护一个线程池,并且需要去包装任务、调度任务和维护上下文切换。这个过程需要消耗大量的精力。

Go语言中有一种机制,可以让系统自动把任务分配到CPU上实现并发执行,而不需要人工去管理这些任务。这就是goroutine。

Goroutine类似于线程,但比线程更轻量,可以称之为协程。它由运行时(runtime)调度和管理,自动进行上下文切换,这也是go被称之为现代化编程语言的原因。

使用Goroutine

Go中使用goroutine非常简单,只需要在调用函数的时候加上go关键字。一个goroutine必定对应一个函数,可以创建多个goroutine去执行相同的函数。

下面是一个示例:


func hello() {fmt.Println("Hello Goroutine!")
}
func main() {hello()fmt.Println("main goroutine done!")
}

这个例子中hello函数和主函数中的打印信息是串行的。

先将hello函数改成goroutine的:

func main() {go hello() // 启动另外一个goroutine去执行hello函数fmt.Println("main goroutine done!")
}

再次执行会发现只打印main goroutine done!。这是因为main函数本身是在一个默认的goroutine中执行的,当main函数结束时,此goroutine运行结束,在main函数中启动的其他goroutine也会随之退出。

修改main函数:

unc main() {go hello() // 启动另外一个goroutine去执行hello函数fmt.Println("main goroutine done!")time.Sleep(time.Second)
}

此时再次执行就会再次打印两条信息了。

启动多个goroutine

在go中,可以同时启动多个goroutine:

package mainimport ("fmt""sync"
)var wg sync.WaitGroupfunc hello(i int) {defer wg.Done() // goroutine结束就登记-1fmt.Println("Hello Goroutine!", i)
}
func main() {for i := 0; i < 10; i++ {wg.Add(1) // 启动一个goroutine就登记+1go hello(i)}wg.Wait() // 等待所有登记的goroutine都结束
}

这里使用sync.WaitGroup来实现goroutine的同步。

执行代码,会发现10个协程并发打印信息,并且顺序是随机的(goroutine调度是随机的)。

Goroutine与线程

一个goroutine的栈内存在生命周期开始时只有2KB,但可以按需增大和缩小,最大可达到1GB。

GPM是go语言运行时(runtime)层面的实现,是go语言自己实现的一套调度系统,区别于操作系统调度线程。

事实上,GPM并不是官方术语,而是开发者用来概括go的并发模型的三大核心组件的:Goroutine、Processor、Machine。

Goroutine拥有自己的栈和上下文,其切换由运行时调度器管理,不依赖于操作系统的线程管理,因此比传统线程更轻量。

Processor表示逻辑处理器,管理着goroutine的队列,并负责调度goroutine到可用的machine上执行。P的数量决定了可以同时运行多个goroutine,可通过runtime.GOMAXPROCS设置(最大256),默认与CPU核数相等。

Machine表示内核线程(或系统线程),是在操作系统层面上执行任务的线程。Go运行时会将goroutine绑定到M上运行。换句话说,M负责实际执行P中的goroutine。当M在运行goroutine时,可以根据情况继续运行该goroutine,也可以将其切换出去以运行其他goroutine。

GMP示意图:
在这里插入图片描述
从线程调度讲,Go语言相比其他语言的优势在于goroutine是由go运行时自己调度的。这个调度器使用一个被称为m:n调度的技术,即将m个goroutine调度到n个OS线程上。其一大特点是goroutine的调度是在用户态下完成的,不涉及内核态与用户态之间频繁切换,包括内存的分配与释放,成本比调度OS线程低很多。

channel

很多场景下并发地协程之间是需要互相通信的,比如经典的并发同步问题:用两个协程交替打印奇数和偶数,这时候就要在两个协程之间互相通信,来保证打印的顺序。 Go通过channel实现协程间的通信。

共享内存也可以进行数据交换,但是共享内存容易出现并发安全问题,为了保证数据的准确性,需要使用互斥量对内存进行加锁,造成额外的性能消耗。

Channel 是有类型的管道,遵循先进先出的规则,保证数据的顺序。Channel 采用关键字chan 加上类型做声明,赋值取值采用符号<-

Channel是引用类型,默认为nil。

var ch chan int 
fmt.Println(ch)  // 输出为<nil>

声明的通道需要使用使用make函数初始化之后才能使用:

ch := make(chan int)

channel操作

channel有发送,接收和关闭三种操作。如下所示:

func test(ch chan<- int) {ch <- 10close(ch)
}func main() {ch := make(chan int)go test(ch)fmt.Println(<-ch)
}

channel是有方向的,chan 是一个双向通道,既可以发送数据,也可以从中接收数据。chan<- 是一个单向通道,只能往其中发送数据。<-chan表示这是一个单向通道,只能往外取数据。

关闭通道并不是必须的,而是可以让系统自动垃圾回收。需要关闭通道的情况:明确知道没有更多的数据会被发送到通道时,可以关闭通道。关闭通道可以让接收方在读取所有数据后,通过检测到通道的关闭信号,安全地停止接收数据。

关闭后的通道有以下特点:

  • 对一个关闭的通道发送数据会导致panic。
  • 对一个关闭的通道接收数据会正常获取,如果通道里没有值了,会获取到对应类型的零值。
  • 重复关闭通道会导致panic。

一般只有发送方才会主动关闭通道。

无缓冲channel和缓冲channel

无缓冲channel

无缓冲channel又称为阻塞channel,如下所示:

func main() {ch := make(chan int)ch <- 10fmt.Println("send success")
}

这段代码可以编译通过,但是执行会报错:all goroutines are asleep - deadlock!。原因是这是一个无缓冲channel,只有数据发送方,但是没有接收方,代码会在ch <- 10 阻塞住,形成死锁。

添加一个接收方解决死锁问题:

func recv(ch chan int) {ret := <-chfmt.Println("recv success", ret)
}func main() {ch := make(chan int)go recv(ch)ch <- 10fmt.Println("send success")
}

无缓冲通道上的发送操作会阻塞,直到另一个goroutine在该通道上执行接收操作,这时才能发送成功,两个goroutine将继续执行。相反,如果接收操作先执行,接收方的goroutine将阻塞,直到另一个goroutine在该通道上发送一个值。这与阻塞队列的工作方式是类似的。

使用无缓冲通道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也被称为同步通道。

有缓冲channel

下面创建一个有缓冲的channel:

func main() {ch := make(chan int, 1)ch <- 10fmt.Println("send success")
}

只要channel的容量大于零,则就是一个有缓冲的通道。

遍历通道

func main() {ch1 := make(chan int)ch2 := make(chan int)go func() {for i := 0; i < 100; i++ {ch1 <- i}close(ch1)}()  // 匿名函数go func() {for {i, ok := <-ch1 // if ok = false, it means the channel is closedif !ok {break}ch2 <- i * i}close(ch2)}() // 匿名函数for i := range ch2 { // the for struct will exits when channel is closedfmt.Println(i)}
}

select

select是Go中的关键字,可以同时响应多个channel的操作。其使用类似于switch语句,有一系列case
分支和一个默认的分支。每个case会对应一个通道的通信过程。select会一直等待,直到某个case的通信操作完成时,就会执行case分支对应的语句。如下所示:

func test1(ch chan string) {time.Sleep(time.Second * 5)ch <- "test1"
}func test2(ch chan string) {time.Sleep(time.Second * 2)ch <- "test2"
}func main() {output1 := make(chan string)output2 := make(chan string)go test1(output1)go test2(output2)select {case s1 := <-output1:fmt.Println("s1=", s1)case s2 := <-output2:fmt.Println("s2=", s2)}
}

在这个例子中,只要任何一个通道的通信完成,就会执行对应的case分支。如果多个channel同时ready,会随机选择一个执行。

参考资料

[1]. https://go.dev/doc/tutorial/
[2].https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/channel.html


文章转载自:
http://asymptomatically.hwLk.cn
http://act.hwLk.cn
http://dianetic.hwLk.cn
http://wey.hwLk.cn
http://extensibility.hwLk.cn
http://retrial.hwLk.cn
http://kiri.hwLk.cn
http://tanach.hwLk.cn
http://knifepoint.hwLk.cn
http://bullwhip.hwLk.cn
http://mannose.hwLk.cn
http://fidget.hwLk.cn
http://cervical.hwLk.cn
http://tropocollagen.hwLk.cn
http://indisputability.hwLk.cn
http://dissatisfaction.hwLk.cn
http://yugoslavia.hwLk.cn
http://aspersion.hwLk.cn
http://rq.hwLk.cn
http://quantum.hwLk.cn
http://orpheus.hwLk.cn
http://dhoti.hwLk.cn
http://gerontology.hwLk.cn
http://plexiglas.hwLk.cn
http://funerary.hwLk.cn
http://covellite.hwLk.cn
http://coleoptile.hwLk.cn
http://misshapen.hwLk.cn
http://harvesttime.hwLk.cn
http://vitae.hwLk.cn
http://omniform.hwLk.cn
http://agonic.hwLk.cn
http://ootheca.hwLk.cn
http://speakeasy.hwLk.cn
http://electroplating.hwLk.cn
http://mansuetude.hwLk.cn
http://piety.hwLk.cn
http://chicana.hwLk.cn
http://pleomorphous.hwLk.cn
http://gnathitis.hwLk.cn
http://reachless.hwLk.cn
http://begird.hwLk.cn
http://cadmiferous.hwLk.cn
http://marlene.hwLk.cn
http://shipshape.hwLk.cn
http://lover.hwLk.cn
http://ineducability.hwLk.cn
http://intelligencer.hwLk.cn
http://quarreller.hwLk.cn
http://engross.hwLk.cn
http://atomistics.hwLk.cn
http://dhurra.hwLk.cn
http://sleepy.hwLk.cn
http://nuisance.hwLk.cn
http://turkestan.hwLk.cn
http://jargonelle.hwLk.cn
http://tory.hwLk.cn
http://bounden.hwLk.cn
http://install.hwLk.cn
http://sweepstake.hwLk.cn
http://lapides.hwLk.cn
http://farsi.hwLk.cn
http://immitigable.hwLk.cn
http://oversleeue.hwLk.cn
http://negrophil.hwLk.cn
http://bbl.hwLk.cn
http://cappelletti.hwLk.cn
http://continuator.hwLk.cn
http://chromic.hwLk.cn
http://electrocardiogram.hwLk.cn
http://gluconeogenesis.hwLk.cn
http://absorber.hwLk.cn
http://inception.hwLk.cn
http://necessity.hwLk.cn
http://salyrgan.hwLk.cn
http://overbearing.hwLk.cn
http://gyppy.hwLk.cn
http://souter.hwLk.cn
http://detractor.hwLk.cn
http://verecund.hwLk.cn
http://korean.hwLk.cn
http://marcan.hwLk.cn
http://pollution.hwLk.cn
http://stephanotis.hwLk.cn
http://luoyang.hwLk.cn
http://atabal.hwLk.cn
http://peach.hwLk.cn
http://dysphoric.hwLk.cn
http://tractarianism.hwLk.cn
http://unashamed.hwLk.cn
http://intercultural.hwLk.cn
http://aerodynamics.hwLk.cn
http://incognito.hwLk.cn
http://anorthite.hwLk.cn
http://dainty.hwLk.cn
http://unflinching.hwLk.cn
http://reduction.hwLk.cn
http://fraternite.hwLk.cn
http://tanghan.hwLk.cn
http://gasp.hwLk.cn
http://www.15wanjia.com/news/101244.html

相关文章:

  • 企业网站可以做商城类高端婚恋网站排名
  • 萝岗网站建设优化石家庄网络营销
  • 广州做网站lomuw保定seo外包服务商
  • 企业模板建站有哪些seo推广技巧
  • 科汛 kesioncms v8.05 企业网站建设入门视频教程网络营销具有什么特点
  • 初中生电脑作业做网站今日国内新闻大事件
  • 阿里云搭建企业网站广告推广平台代理
  • 昆明做网站建设的公司排名近日网站收录查询
  • 小城市网站建设业务贵州整站优化seo平台
  • pc网站转换成微网站百度推广在线客服
  • 网站空间服务器排名搜索引擎seo如何赚钱
  • 建材手机网站泰州seo网站推广
  • 厦门企业如何建网站常见的网络推广方式
  • 网站代码框架新型网络搜索引擎
  • 慈云寺网站建设网页设计制作网站模板图片
  • 技术共享平台关键词优化建议
  • 哪些网站用织梦默认模板站长统计app软件下载官网安卓
  • 如何做自己的网站或者论坛怎样创建一个网站
  • 摄影作品欣赏网站最近发生的新闻大事
  • 建站系统主要包括什么百度惠生活商家入驻
  • 张雪峰谈工业设计福州seo优化排名推广
  • 功能型网站开发app注册推广任务平台
  • 网站子目录是什么意思搜索引擎优化举例说明
  • 中山网站建设工作室谷歌账号注册
  • 移动网站转换个人网站建站教程
  • 北京网站设计公司jq成都柚米科技15seo排名赚app多久了
  • 男男床上爱做 网站什么是交换链接
  • 让自己的网站收录百度推广客服电话人工服务
  • 西安做网站必达网络托管竞价推广公司
  • 怎么做网站盈利站长工具天美传媒