WaitGroup
-
实现并发控制
- 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式的并发模型
主协程如何等其余协程完再操作
- 使用channel进行通信,context,select
slice,len,cap,共享,扩容
- 切片的扩容策略:
https://www.jianshu.com/p/54be5b08a21c
片的数据结构中,包含一个指向数组的指针 array ,当前长度 len ,以及最大容量 cap 。
在不声明 cap 的情况下,默认 cap=len 。当切片长度没有超过容量时,对切片新增数据,不会改变 array 指针的值。
当对切片进行 append 操作,导致长度超出容量时,就会创建新的数组,这会导致和原有切片的分离。 - 当需要的容量超过原切片容量的两倍时,会使用需要的容量作为新容量。
- 当原切片长度小于1024时,新切片的容量会直接翻倍。而当原切片的容量大于等于1024时,会反复地增加25%,直到新容量超过所需要的容量。
map如何顺序读取
- map不能顺序读取,是因为他是无序的,想要有序读取,首先的解决的问题就是,把key变为有序,所以可以把key放入切片,对切片进行排序,遍历切片,通过key取值。
实现set
孤儿进程和僵尸进程
实现消息队列(多生产者,多消费者)
大文件排序
go defer
- 创建延迟调用
new与make
- 二者都是为引用类型分配内存,但是new是不完全创建,以字典为例,new只分配了字典类型本身所需内存,并没有分配键值存储内存;
孤儿进程,僵尸进程
go struct能否比较
- https://www.jianshu.com/p/d84a2a067cef
- 同一个struct的2个实例能不能比较
-
两个不同的struct的实例能不能比较(可以能,也可以不能)
- 可排序、可比较和不可比较
- 可排序的数据类型有三种,Integer,Floating-point,和String
- 可比较的数据类型除了上述三种外,还有Boolean,Complex,Pointer,Channel,Interface和Array
- 不可比较的数据类型包括,Slice, Map, 和Function
- struct可以作为map的key么?
- struct必须是可比较的,才能作为key,否则编译时报错
简述一下golang的协程调度原理
- 多个线程可以属于同一个进程并共享内存空间。因为多线程不需要创建新的虚拟内存空间,所以它们也不需要内存管理单元处理上下文的切换,线程之间的通信也正是基于共享的内存进行的,与重量级的进程相比,线程显得比较轻量。
-
go调度器组成部分:
- 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是否准备完毕:可读或可写。
go语言和其他语言的比较
- Go语言的并发是基于 goroutine 的,goroutine 类似于线程,但并非线程。可以将 goroutine 理解为一种虚拟线程。Go 语言运行时会参与调度 goroutine,并将 goroutine 合理地分配到每个 CPU 中,最大限度地使用CPU性能。开启一个goroutine的消耗非常小(大约2KB的内存),你可以轻松创建数百万个goroutine。
数组和切片的区别:
- 数组是一种具有相同类型固定大小的一种数据结构。
- 切片并不存储任何元素而只是对现有数组的引用(不是值拷贝,是指针)
- 切片的底层就是数组,切片是通过指针的形式指向不同数组的位置从而形成不同的切片,切片对本身元素的修改,也会影响到数组和其它的切片
值类型和引用类型
- 值类型:golang基本的数据类型,int,float,struct,bool,string,数组
- 引用类型:指针,slice,map,channel, interface
本质区别:值类型内存中变量存储的是具体的值,引用类型变量存储的是地址,地址指向的空间存的才是值;
go垃圾回收机制GC
- 触发机制:
有疑问加站长微信联系(非本文作者)