Golang面试前一夜准备:6-10题

简介: Golang面试前一夜准备:6-10题

640.png

Golang面试前一夜准备



题号 题目
6 协程和线程和进程的区别
7 Golang的内存模型中为什么小对象多了会造成GC压力
8 Go中数据竞争问题怎么解决
9 什么是channel,为什么它可以做到线程安全
10 Golang垃圾回收算法


6. 协程和线程和进程的区别


  • 进程


进程是程序的一次执行过程,是程序在执行过程中的分配和管理资源的基本单位,每个进程都有自己的地址空间,进程是系统进行资源分配和调度的一个独立单位。

每个进程都有自己的独立内存空间,不同进程通过IPC(Inter-Process Communication)进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。


  • 线程

线程是进程的一个实体,线程是内核态,而且是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。


线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。


  • 协程

协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。


协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。


7. Golang的内存模型中为什么小对象多了会造成GC压力


通常小对象过多会导致GC三色法消耗过多的CPU。优化思路是,减少对象分配(内存分配请看往期文章).


8. Go中数据竞争问题怎么解决


Data Race问题可以使用互斥锁sync.Mutex, 或者也可以通过CAS无锁并发解决.


其中使用同步访问共享数据或者CAS无锁并发是处理数据竞争的一种有效的方法.


golang在1.1之后引入了竞争检测机制,可以使用 go run -race 或者 go build -race来进行静态检测。


其在内部的实现是,开启多个协程执行同一个命令, 并且记录下每个变量的状态.


竞争检测器基于C/C++的ThreadSanitizer运行时库,该库在Google内部代码基地和Chromium找到许多错误。这个技术在2012年九月集成到Go中,从那时开始,它已经在标准库中检测到42个竞争条件。现在,它已经是我们持续构建过程的一部分,当竞争条件出现时,它会继续捕捉到这些错误。


竞争检测器已经完全集成到Go工具链中,仅仅添加-race标志到命令行就使用了检测器。


$ go test -race mypkg    // 测试包
$ go run -race mysrc.go  // 编译和运行程序
$ go build -race mycmd   // 构建程序
$ go install -race mypkg // 安装程序

要想解决数据竞争的问题可以使用互斥锁sync.Mutex,解决数据竞争(Data race),也可以使用管道解决,使用管道的效率要比互斥锁高.


9. 什么是channel,为什么它可以做到线程安全


Channel是Go中的一个核心类型,可以把它看成一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯(communication),Channel也可以理解是一个先进先出的队列,通过管道进行通信。


Golang的Channel,发送一个数据到Channel和从Channel接收一个数据都是原子性的。

Go的设计思想就是, 不要通过共享内存来通信,而是通过通信来共享内存,前者就是传统的加锁,后者就是Channel。


也就是说,设计Channel的主要目的就是在多任务间传递数据的,本身就是安全的。


10. Golang垃圾回收算法


Golang 1.5后,采取的是“非分代的、非移动的、并发的、三色的”标记清除垃圾回收算法。

golang 中的 gc 基本上是标记清除的过程:

640.png


golang 的垃圾回收是基于标记清扫算法,这种算法需要进行 STW(stop the world),这个过程就会导致程序是卡顿的,频繁的 GC 会严重影响程序性能.


golang 在此基础上进行了改进,通过三色标记清扫法与写屏障来减少 STW 的时间.

gc的过程一共分为四个阶段:


  1. 栈扫描(开始时STW),所有对象最开始都是白色.
  2. 从 root开始找到所有可达对象(所有可以找到的对象),标记为灰色,放入待处理队列。
  3. 遍历灰色对象队列,将其引用对象标记为灰色放入待处理队列,自身标记为黑色。
  4. 清除(并发) 循环步骤3直到灰色队列为空为止,此时所有引用对象都被标记为黑色,所有不可达的对象依然为白色,白色的就是需要进行回收的对象。三色标记法相对于普通标记清扫,减少了 STW 时间. 这主要得益于标记过程是 "on-the-fly" 的,在标记过程中是不需要 STW 的,它与程序是并发执行的,这就大大缩短了STW的时间.


Golang gc 优化的核心就是尽量使得 STW(Stop The World) 的时间越来越短。

更加详细的GC我会在后面单独章节拿出来讲解(源码+图解),为了应付面试这些就足够了。

写屏障:


当标记和程序是并发执行的,这就会造成一个问题. 在标记过程中,有新的引用产生,可能会导致误清扫.

清扫开始前,标记为黑色的对象引用了一个新申请的对象,它肯定是白色的,而黑色对象不会被再次扫描,那么这个白色对象无法被扫描变成灰色、黑色,它就会最终被清扫,而实际它不应该被清扫.

这就需要用到屏障技术,golang采用了写屏障,其作用就是为了避免这类误清扫问题. 写屏障即在内存写操作前,维护一个约束,从而确保清扫开始前,黑色的对象不能引用白色对象.


GC的触发条件:


Go中对 GC 的触发时机存在两种形式:

  1. 主动触发(手动触发),通过调用runtime.GC 来触发GC,此调用阻塞式地等待当前GC运行完毕.
  2. 被动触发,分为两种方式:a. 使用系统监控,当超过两分钟没有产生任何GC时,强制触发 GC. b. 使用步调(Pacing)算法,其核心思想是控制内存增长的比例,当前内存分配达到一定比例则触发.
相关文章
|
2月前
|
Go
golang力扣leetcode 面试题04.06.后继者
golang力扣leetcode 面试题04.06.后继者
34 0
|
2月前
|
Go
golang力扣leetcode 面试题01.05.一次编辑
golang力扣leetcode 面试题01.05.一次编辑
30 0
|
2月前
|
安全 Go 开发者
Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello("Alice")`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
37 1
|
2月前
|
Java Go
Golang深入浅出之-Go语言指针面试必知:理解与使用指针
【4月更文挑战第21天】Go语言中的指针允许直接操作内存,常用于高效数据共享和传递。本文介绍了指针的基础知识,如声明、初始化和解引用,以及作为函数参数使用。此外,讨论了`new()`与`make()`的区别和内存逃逸分析。在结构体上下文中,指针用于减少复制开销和直接修改对象。理解指针与内存管理、结构体的关系及常见易错点,对于面试和编写高性能Go代码至关重要。
30 2
|
2月前
|
存储 Go 开发者
Golang深入浅出之-Go语言字符串操作:常见函数与面试示例
【4月更文挑战第20天】Go语言字符串是不可变的字节序列,采用UTF-8编码。本文介绍了字符串基础,如拼接(`+`或`fmt.Sprintf()`)、长度与索引、切片、查找与替换(`strings`包)以及转换与修剪。常见问题包括字符串不可变性、UTF-8编码处理、切片与容量以及查找与替换的边界条件。通过理解和实践这些函数及注意事项,能提升Go语言编程能力。
42 0
|
2月前
|
监控 编译器 Linux
golang面试:golang的GPM调度模型(七)
golang面试:golang的GPM调度模型(七)
37 1
|
2月前
|
监控 安全 Go
golang面试:golang中的context(四)
golang面试:golang中的context(四)
48 0
|
2月前
|
监控 算法 Go
Golang深入浅出之-Go语言中的服务熔断、降级与限流策略
【5月更文挑战第4天】本文探讨了分布式系统中保障稳定性的重要策略:服务熔断、降级和限流。服务熔断通过快速失败和暂停故障服务调用来保护系统;服务降级在压力大时提供有限功能以保持整体可用性;限流控制访问频率,防止过载。文中列举了常见问题、解决方案,并提供了Go语言实现示例。合理应用这些策略能增强系统韧性和可用性。
127 0
|
2月前
|
前端开发 Go
Golang深入浅出之-Go语言中的异步编程与Future/Promise模式
【5月更文挑战第3天】Go语言通过goroutines和channels实现异步编程,虽无内置Future/Promise,但可借助其特性模拟。本文探讨了如何使用channel实现Future模式,提供了异步获取URL内容长度的示例,并警示了Channel泄漏、错误处理和并发控制等常见问题。为避免这些问题,建议显式关闭channel、使用context.Context、并发控制机制及有效传播错误。理解并应用这些技巧能提升Go语言异步编程的效率和健壮性。
74 5
Golang深入浅出之-Go语言中的异步编程与Future/Promise模式
|
2月前
|
Prometheus 监控 Cloud Native
Golang深入浅出之-Go语言中的分布式追踪与监控系统集成
【5月更文挑战第4天】本文探讨了Go语言中分布式追踪与监控的重要性,包括追踪的三个核心组件和监控系统集成。常见问题有追踪数据丢失、性能开销和监控指标不当。解决策略涉及使用OpenTracing或OpenTelemetry协议、采样策略以及聚焦关键指标。文中提供了OpenTelemetry和Prometheus的Go代码示例,强调全面可观测性对微服务架构的意义,并提示选择合适工具和策略以确保系统稳定高效。
171 5