Golang面试精编2:并发相关

简述goroutine调度器模型?
go为什么有如此强大的并发能力?——得益于其goroutine调度器
简述goroutine并发模型?
以上三种提问的回答都是一样的,就是说明MPG调度器模型;

  • MPG模型:goroutine的并发模型可以归纳为MPG模型;
  • MPG概念:线程(machine,系统线程,物理线程)-内核(processor)-协程(goroutine,用户线程,逻辑线程);
  • 多对多调度模型:整体调度遵循多对多模型,多个协程(约百万级)同时调度在多个线程(约千级)下;
  • LRQ(LocalRunningQueue):本地运行队列,一个M执行在一个P的上下文中,P中挂载着一个G队列;
  • GRQ(GlobalRunningQueue):全局运行队列,G没有初始化时或者没有LRQ可供挂载时就被丢入GRQ;
  • GRQ=>LRQ:MP会在LRQ执行完毕检查GRQ,并从中窃取任务挂载到当前LRQ中执行,平时也会定期检查;
  • 调度的目的:调度的目的是防止线程堵塞、闲置、被OS挂起(syscall);
  • 防止线程M堵塞:G1协程IO时脱离MP,G2从当前MP的LRQ中弹出并执行;
  • 防止线程M闲置:M1闲置时,会从M2的LRQ中窃取一半任务,挂载到自己的LRQ中执行;
  • 防止线程M被OS挂起(syscall):P带着LRQ挂到其它线程的下面执行,当syscall结束时,M会尝试将G0挂载到其它LRQ中或GRQ中;
  • 详细go调度器模型参考:
    Go语言中文网:https://studygolang.com/articles/9610
    简书:https://www.jianshu.com/p/f9024e250ac6

select可以用于什么?

  • 随机选择一条没有被读写阻塞的case加以执行,通常是管道IO;

主协程如何等其余协程完再操作?

  • 等待组;
  • 10条子协程,每个子协程结束任务时向一个切片中写入true,主协程循环查看切片的长度,为10时退出;

什么情况下会死锁,如何避免?

  • 主协程被阻塞;
    如何避免:
  • 不能单个协程自读字写一个没有缓冲能力的管道;
  • A协程要求B协程先写入自己再读出,B协程要求A协程先读出自己再写入,此时AB死锁;
  • range channel时,要注意channel的写入关闭,如果不关闭管道,range channel就永远阻塞;

Go的channel,有缓冲和无缓冲的区别是什么?

  • 有缓冲的管道,即使没人写入,也能读出若干默认值,即使没人读出,也能写入若干值;
  • 无缓冲的管道,只要没有协程写入就读出阻塞,没有协程读出,就造成写入阻塞;

go语言可以怎样做同步调度?

  • 通过管道的读写阻塞实现同步;
  • 通过Timer或Ticker实现固定时长阻塞或周期性定时阻塞;
    sync包下的同步机制:
  • 读写锁的抢锁与释放阻塞;
  • 等待组,wg.Wait()直到wg中的所有协程全部wg.Done();
  • 条件变量,cond.Wait()到有人cond.Signal()或cond.Broadcast();
  • Once.Do(func)保证只执行一次;
  • 通过原子操作保证对基本类型变量的操作是同步的;

怎么使用channel实现定时器?

  • 实际上是两个协程同步

你可能感兴趣的:(Go语言面试题)