跟着算法学GO(12)

155 阅读3分钟

「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战

生命不息,学习不止

题外话

初七啦,在座的各位都开工了吧,开工大吉,美好的假期已经离我们而去,我们唯有振作精神,努力奋斗,专心搞钱,再说一遍,女足yyds!

image.png

废话不多说,上货

在这里插入图片描述

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()未执行时其他线程不会执行的原因。

你以为结束了

下回不打算在刷题了,我打算搞个开源项目看看框架,然后学一学,嘿嘿嘿

下一篇就讲,敬请期待

在这里插入图片描述

大家看完发现有什么错误,写在下面吧!跟我黑虎阿福比划比划! 在这里插入图片描述