Golang面试前二夜准备:18-20题

简介: Golang面试前二夜准备:18-20题

640.png

Golang面试前二夜准备



题号 题目
18 怎么限制Goroutine的数量
19 Channel是同步的还是异步的
20 Goroutine和线程的区别


18. 怎么限制Goroutine的数量


在Golang中,Goroutine虽然很好,但是数量太多了,往往会带来很多麻烦,比如耗尽系统资源导致程序崩溃,或者CPU使用率过高导致系统忙不过来。


所以我们可以限制下Goroutine的数量,这样就需要在每一次执行go之前判断goroutine的数量,如果数量超了,就要阻塞go的执行。


所以通常我们第一时间想到的就是使用带cap的通道(chan)。每次执行go func(负责消费chan)之前向通道写入值,直到通道满的时候就阻塞了,这样就相当于限制了goroutine的并发数。但是当main结束的时候,因为并不是所有的goroutine都执行完了,在main函数退出之后,这些goroutine就被强制结束了。这个时候我们就需要用到sync.WaitGroup。使用WaitGroup等待所有的goroutine退出。


package main
import (
 "fmt"
 "sync"
)
var ch chan  int
func elegance(wg *sync.WaitGroup){
 defer wg.Done()
 select {
 case ret := <- ch:
  fmt.Println(ret)
 }
}
func main(){
 ch = make(chan int,5) //控制并发
 wg := sync.WaitGroup{}
 for i:=0;i<10;i++{
  wg.Add(1)
  ch <-i //五个之后就会阻塞 除非有goroutine消费了chan 可以继续并发  但是上限是5
  go elegance(&wg)
 }
 wg.Wait()
 fmt.Println("end")
}


19. Channel是同步的还是异步的


Channel是异步进行的, channel存在3种状态:

  • nil,未初始化的状态,只进行了声明,或者手动赋值为nil
  • active,正常的channel,可读或者可写
  • closed,已关闭,千万不要误认为关闭channel后,channel的值是nil


下面我们对channel的三种操作解析:

  1. 零值(nil)通道;
  2. 非零值但已关闭的通道;
  3. 非零值并且尚未关闭的通道。


操作 一个零值nil通道 一个非零值但已关闭的通道 一个非零值且尚未关闭的通道
关闭 产生恐慌 产生恐慌 成功关闭
发送数据 永久阻塞 产生恐慌 阻塞或者成功发送
接收数据 永久阻塞 永不阻塞 阻塞或者成功接收


20. Goroutine和线程的区别


从调度上看,goroutine的调度开销远远小于线程调度开销


OS的线程由OS内核调度,每隔几毫秒,一个硬件时钟中断发到CPU,CPU调用一个调度器内核函数。这个函数暂停当前正在运行的线程,把他的寄存器信息保存到内存中,查看线程列表并决定接下来运行哪一个线程,再从内存中恢复线程的注册表信息,最后继续执行选中的线程。这种线程切换需要一个完整的上下文切换:即保存一个线程的状态到内存,再恢复另外一个线程的状态,最后更新调度器的数据结构。某种意义上,这种操作还是很慢的。


Go运行的时候包涵一个自己的调度器,这个调度器使用一个称为一个M:N调度技术,m个goroutine到n个os线程(可以用GOMAXPROCS来控制n的数量),Go的调度器不是由硬件时钟来定期触发的,而是由特定的go语言结构来触发的,他不需要切换到内核语境,所以调度一个goroutine比调度一个线程的成本低很多。


从栈空间上,goroutine的栈空间更加动态灵活


每个OS的线程都有一个固定大小的栈内存,通常是2MB,栈内存用于保存在其他函数调用期间哪些正在执行或者临时暂停的函数的局部变量。这个固定的栈大小,如果对于goroutine来说,可能是一种巨大的浪费。作为对比goroutine在生命周期开始只有一个很小的栈,典型情况是2KB, 在go程序中,一次创建十万左右的goroutine也不罕见(2KB*100,000=200MB)。而且goroutine的栈不是固定大小,它可以按需增大和缩小,最大限制可以到1GB。


goroutine没有一个特定的标识。


在大部分支持多线程的操作系统和编程语言中,线程有一个独特的标识,通常是一个整数或者指针,这个特性可以让我们构建一个线程的局部存储,本质是一个全局的map,以线程的标识作为键,这样每个线程可以独立使用这个map存储和获取值,不受其他线程干扰。


goroutine中没有可供程序员访问的标识,原因是一种纯函数的理念,不希望滥用线程局部存储导致一个不健康的超距作用,即函数的行为不仅取决于它的参数,还取决于运行它的线程标识。


相关文章
|
3月前
|
存储 安全 算法
golang面试:golang实现原理(二)
golang面试:golang实现原理(二)
34 0
|
2天前
|
安全 Go 开发者
Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello(&quot;Alice&quot;)`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
10 1
|
3月前
|
监控 编译器 Linux
golang面试:golang的GPM调度模型(七)
golang面试:golang的GPM调度模型(七)
31 1
|
3月前
|
监控 安全 Go
golang面试:golang中的context(四)
golang面试:golang中的context(四)
44 0
|
3月前
|
安全 Linux Go
golang面试:golang并发与多线程(三)
golang面试:golang并发与多线程(三)
45 0
|
3月前
|
JSON 安全 Java
golang面试:golang基础语法(一)
golang面试:golang基础语法(一)
41 0
|
9月前
|
缓存 并行计算 算法
Golang面试前三夜准备:Goroutine调度器GMP为何需要P?不需要会怎样?
Golang面试前三夜准备:Goroutine调度器GMP为何需要P?不需要会怎样?
|
29天前
|
Java 程序员
java线程池讲解面试
java线程池讲解面试
52 1
|
2月前
|
存储 关系型数据库 MySQL
2024年Java秋招面试必看的 | MySQL调优面试题
随着系统用户量的不断增加,MySQL 索引的重要性不言而喻,对于后端工程师,只有在了解索引及其优化的规则,并应用于实际工作中后,才能不断的提升系统性能,开发出高性能、高并发和高可用的系统。 今天小编首先会跟大家分享一下MySQL 索引中的各种概念,然后介绍优化索引的若干条规则,最后利用这些规则,针对面试中常考的知识点,做详细的实例分析。
251 0
2024年Java秋招面试必看的 | MySQL调优面试题
|
2月前
|
存储 算法 Java
铁子,你还记得这些吗----Java基础【拓展面试常问题型】
铁子,你还记得这些吗----Java基础【拓展面试常问题型】
46 1