WaitGroup

  • 实现并发控制

    image.png
  • Add与Done应该放在哪? – Add放在Goroutine外,Done放在Goroutine中,逻辑复杂时建议用defer保证调用
  • WaitGroup适合什么样的场景? – 并发的Goroutine执行的逻辑相同时,否则代码并不简洁,可以采用其它方式
  • 理解WaitGroup的实现 – 核心是CAS的使用
    https://blog.csdn.net/weixin_34259159/article/details/91699572
    Done()只做一件事,即把counter减1,我们知道Add()可以接受负值,所以Done实际上只是调用了Add(-1)。

上下文 Context以及设计原理

  • 创建多个 Goroutine 来处理一次请求,而 context.Context 的作用就是在不同 Goroutine 之间同步请求特定数据、取消信号以及处理请求的截止日期。
  • 每一个 context.Context 都会从最顶层的 Goroutine 一层一层传递到最下层。
    context.Context 可以在上层 Goroutine 执行出现错误时,将信号及时同步给下层。

简约语言:golang; CSP式的并发模型

  • http://interview.wzcu.com/Golang/CSP.html

  • image.png
  • image.png
  • image.png

    image.png

    image.png
  • image.png
  • image.png
  • image.png
  • image.png

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

  • 使用channel进行通信,context,select

slice,len,cap,共享,扩容

  • 切片的扩容策略:
    https://www.jianshu.com/p/54be5b08a21c
    片的数据结构中,包含一个指向数组的指针 array ,当前长度 len ,以及最大容量 cap 。
    在不声明 cap 的情况下,默认 cap=len 。当切片长度没有超过容量时,对切片新增数据,不会改变 array 指针的值。
    当对切片进行 append 操作,导致长度超出容量时,就会创建新的数组,这会导致和原有切片的分离。
  • 当需要的容量超过原切片容量的两倍时,会使用需要的容量作为新容量。
  • 当原切片长度小于1024时,新切片的容量会直接翻倍。而当原切片的容量大于等于1024时,会反复地增加25%,直到新容量超过所需要的容量。
  • image.png

map如何顺序读取

  • map不能顺序读取,是因为他是无序的,想要有序读取,首先的解决的问题就是,把key变为有序,所以可以把key放入切片,对切片进行排序,遍历切片,通过key取值。
  • image.png

实现set

  • image.png

孤儿进程和僵尸进程

  • image.png

实现消息队列(多生产者,多消费者)

大文件排序

go defer

  • 创建延迟调用

new与make

  • 二者都是为引用类型分配内存,但是new是不完全创建,以字典为例,new只分配了字典类型本身所需内存,并没有分配键值存储内存;

孤儿进程,僵尸进程

go struct能否比较

  • https://www.jianshu.com/p/d84a2a067cef
  • 同一个struct的2个实例能不能比较
  • 两个不同的struct的实例能不能比较(可以能,也可以不能)

    image.png
  • 可排序、可比较和不可比较
    • 可排序的数据类型有三种,Integer,Floating-point,和String
    • 可比较的数据类型除了上述三种外,还有Boolean,Complex,Pointer,Channel,Interface和Array
    • 不可比较的数据类型包括,Slice, Map, 和Function
  • struct可以作为map的key么?
    • struct必须是可比较的,才能作为key,否则编译时报错

简述一下golang的协程调度原理

  • 多个线程可以属于同一个进程并共享内存空间。因为多线程不需要创建新的虚拟内存空间,所以它们也不需要内存管理单元处理上下文的切换,线程之间的通信也正是基于共享的内存进行的,与重量级的进程相比,线程显得比较轻量。
  • go调度器组成部分:

    image.png
  • G: Goroutine 只存在于 Go 语言的运行时,它是 Go 语言在用户态提供的线程,作为一种粒度更细的资源调度单元,如果使用得当能够在高并发的场景下更高效地利用机器的 CPU。
  • M:Go 语言并发模型中的 M 是操作系统线程。调度器最多可以创建 10000 个线程,但是其中大多数的线程都不会执行用户代码(可能陷入系统调用),最多只会有 GOMAXPROCS 个活跃线程能够正常运行。在默认情况下,运行时会将 GOMAXPROCS 设置成当前机器的核数,我们也可以使用 runtime.GOMAXPROCS 来改变程序中最大的线程数。
  • P: 调度器中的处理器 P 是线程和 Goroutine 的中间层,它能提供线程需要的上下文环境,也会负责调度线程上的等待队列,通过处理器 P 的调度,每一个内核线程都能够执行多个 Goroutine,它能在 Goroutine 进行一些 I/O 操作时及时切换,提高线程的利用率。

go运行时runtime

  • 这个 runtime 类似 Java 和 .NET 语言所用到的虚拟机,它负责管理包括内存分配、垃圾回收。
  • runtime 主要由 C 语言编写,并且是每个 Go 包的最顶级包。

go select

  • golang 的 select 就是监听 IO 操作,当 IO 操作发生时,触发相应的动作每个case语句里必须是一个IO操作,确切的说,应该是一个面向channel的IO操作
  • Go 的select语句是一种仅能用于channl发送和接收消息的专用语句,此语句运行期间是阻塞的;当select中没有case语句的时候,会阻塞当前的groutine。所以,有人也会说select是用来阻塞监听goroutine的。
    还有人说:select是Golang在语言层面提供的I/O多路复用的机制,其专门用来检测多个channel是否准备完毕:可读或可写。
  • image.png

go语言和其他语言的比较

  • image.png
  • Go语言的并发是基于 goroutine 的,goroutine 类似于线程,但并非线程。可以将 goroutine 理解为一种虚拟线程。Go 语言运行时会参与调度 goroutine,并将 goroutine 合理地分配到每个 CPU 中,最大限度地使用CPU性能。开启一个goroutine的消耗非常小(大约2KB的内存),你可以轻松创建数百万个goroutine。

数组和切片的区别:

  • 数组是一种具有相同类型固定大小的一种数据结构。
  • 切片并不存储任何元素而只是对现有数组的引用(不是值拷贝,是指针)
  • 切片的底层就是数组,切片是通过指针的形式指向不同数组的位置从而形成不同的切片,切片对本身元素的修改,也会影响到数组和其它的切片

值类型和引用类型

  • 值类型:golang基本的数据类型,int,float,struct,bool,string,数组
  • 引用类型:指针,slice,map,channel, interface
    本质区别:值类型内存中变量存储的是具体的值,引用类型变量存储的是地址,地址指向的空间存的才是值;

go垃圾回收机制GC

  • 触发机制:
  • image.png
  • image.png

文章来源于互联网,如有雷同请联系站长删除:GO

发表评论