「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」
生命不息,学习不止
题外话
初七啦,在座的各位都开工了吧,开工大吉,美好的假期已经离我们而去,我们唯有振作精神,努力奋斗,专心搞钱,再说一遍,女足yyds!
废话不多说,上货
LeetcCode-1114
1114. 按序打印
还是这道题,因为还有知识点没有讲完
题目如下:
给你一个类:
public class Foo {
public void first() { print("first"); }
public void second() { print("second"); }
public void third() { print("third"); }
}
三个不同的线程 A、B、C 将会共用一个 Foo 实例。
线程 A 将会调用 first() 方法 线程 B 将会调用 second() 方法 线程 C 将会调用 third() 方法 请设计修改程序,以确保 second() 方法在 first() 方法之后被执行,third() 方法在 second() 方法之后被执行。
go实现算法
var secondChan = make(chan struct{})
var thirdChan = make(chan struct{})
var mainChan = make(chan struct{})
func first() {
fmt.Print("first")
secondChan <- struct{}{}
}
func second() {
<-secondChan
fmt.Print("second")
thirdChan <- struct{}{}
close(secondChan)
}
func third() {
<-thirdChan
fmt.Print("third")
mainChan <- struct{}{}
close(thirdChan)
}
func main() {
funcMap := map[int]func(){1: first, 2: second, 3: third}
for _, v := range funcMap {
go v()
}
<-mainChan
小问题回顾
小问题: goroutine为什么叫做轻量级线程?为什么go要使用它?具体实现是怎样的?
轻量级线程goroutine
我们都知道GO语言一个最突出的特点就是在语言层面支持并发,但大家不知道的是,其实每一个go程序至少都包含了一个轻量级线程Goroutine。
但goroutine究竟是什么,在我的理解中,goroutine就是协程。
协程可以成为微线程,一听这名大家就大概明白了,协程一定比线程小很多,不然怎么能叫微呢。
我们都知道进程包含多个线程,同样线程包含多个比他小的协程,很关键的一点就是,协程并不再像线程一样将自己交给系统内核去管理,而是完全由程序去控制,也就是由用户去控制(用户态),这也就是为什么说go在语言层面支持并发了。
go为什么选择goroutine
作为一个面向并发为主的语言,大量的并发情境下一定考虑的就是资源的开销。
线程上下文的切换已经状态的转变是比较消耗性能的,协程的切换一般由程序员在代码中显式控制。它避免了上下文切换的额外耗费,这样在庞大的并发情况下也能有很好的表现。
同时,goroutine非常小,每个goroutine的堆栈只有几kb,并且堆栈可根据程序的需要增长和缩小(线程的堆栈需指明和固定),并且执行goroutine也只需极少的栈内存(大概是4~5KB)。
这些可能是go选择goroutine的原因吧。
go通道阻塞
说了通道数据的接收与发送,大概多少就能明白为什么通道可以按指定顺序完成
从发送端来说,接收者未准备接收数据之前,一直都是阻塞的,同时,发送端未发送数据时,接收端也是阻塞的,这也就是算法中当first()未执行时其他线程不会执行的原因。
你以为结束了
下回不打算在刷题了,我打算搞个开源项目看看框架,然后学一学,嘿嘿嘿
下一篇就讲,敬请期待
大家看完发现有什么错误,写在下面吧!跟我黑虎阿福比划比划!