Skip to content

多核CPU场景下,cache如何保持一致、不冲突?

在多核CPU中,每个CPU核心都有自己的cache(L1、L2 cache),这些cache之间是独立的。如果多个CPU核心同时操作一块内存,就可能出现cache一致性问题。常用的解决方式有MESI协议(Modified、Exclusive、Shared、Invalid四种状态的缩写)、MOSI协议等等,这些都是硬件层面的解决方案,对于开发者来说是透明的。

uint类型溢出

uint是无符号整数类型,当uint类型的值达到其最大值后,如果再进行加1操作,就会回到0,这就是所谓的uint类型溢出。例如,对于uint8类型(范围是0-255),如果其值已经是255,再加1就会变成0。

介绍rune类型

rune在Go语言中是int32的别名,主要用于表示Unicode字符。它可以表示一个Unicode码点,因此可以用来处理任何语言的字符。

编程题:3个函数分别打印cat、dog、fish,要求每个函数都要起一个goroutine,按照cat、dog、fish顺序打印在屏幕上100次。

package
   
   import (
       "fmt"
       "sync"
   )
   
   func main() {
       var wg sync.WaitGroup
       wg.Add(3)
       cat := make(chan bool)
       dog := make(chan bool)
       fish := make(chan bool)
   
       go func() {
           defer wg.Done()
           for i := 0; i < 100; i++ {
               fmt.Println("cat")
               dog <- true
               <-fish
           }
       }()
   
       go func() {
           defer wg.Done()
           for i := 0; i < 100; i++ {
               <-dog
               fmt.Println("dog")
               fish <- true
           }
       }()
   
       go func() {
           defer wg.Done()
           for i := 0; i < 100; i++ {
               <-fish
               fmt.Println("fish")
               cat <- true
           }
       }()
   
       cat <- true
       wg.Wait()
   }

介绍一下channel,无缓冲和有缓冲区别

channel是Go语言中的一种特殊类型,可以用来在goroutine之间传递数据。channel以被看作是一种同步的通信机制,用于在不同的goroutine之间传递数据。 无缓冲的channel:在创建时没有指定缓冲区大小(即容量为0),这意味着发送操作(channel <- data)会阻塞直到另一个goroutine接收这个值(data := <- channel)。无缓冲的channel强制发送和接收的goroutine同步,确保数据的准确传递。
有缓冲的channel:在创建时指定了缓冲区大小(即容量大于0),这样发送操作只有在缓冲区未满时才会阻塞。接收操作也只有在缓冲区非空时才会阻塞。有缓冲的channel允许发送和接收操作在goroutine之间进行异步通信,发送方不需要等待接收方即可继续执行。
无缓冲的channel适用于强调同步的场景,而有缓冲的channel适用于异步通信的场景,具体使用哪种取决于实际需求。

是否了解channel底层实现,比如实现channel的数据结构是什么?

channel的底层实现是通过一个环形队列来完成的,具体数据结构是hchan(在runtime包中定义)。它包含了一些元数据信息,如缓冲区的长度、发送和接收的索引等。当有数据发送到channel或从channel接收数据时,数据会被存储在环形队列中,并根据发送和接收的索引进行更新和同步操作。

channel是否线程安全?

是的,channel是Go语言中的线程安全类型。多个goroutine可以同时读写一个channel,而不会产生数据竞争的问题。这是因为channel在实现上使用了互斥锁和其他同步机制来保证并发访问的安全性。因此,开发者可以放心地在多个goroutine之间共享并操作同一个channel。

Mutex是悲观锁还是乐观锁?悲观锁、乐观锁是什么?

Mutex是一种悲观锁。悲观锁的思想是,在访问共享资源之前,假设其他线程可能会对该资源进行修改,因此需要先对资源进行加锁,保证只有一个线程能够访问,其他线程需要等待锁的释放。

相对地,乐观锁的思想是,不对共享资源进行加锁,而是在修改资源之前先检查是否有其他线程修改了该资源,如果没有则进行修改,

Mutex几种模式?

Mutex可以做自旋锁吗?

介绍一下RWMutex

项目中用过的锁?

介绍一下线程安全的共享内存方式

介绍一下goroutine

goroutine自旋占用cpu如何解决(go调用、gmp)

介绍linux系统信号

goroutine抢占时机(gc 栈扫描)

Gc触发时机

是否了解其他gc机制

Go内存管理方式

Channel分配在栈上还是堆上?哪些对象分配在堆上,哪些对象分配在栈上?

介绍一下大对象小对象,为什么小对象多了会造成gc压力?

项目中遇到的oom情况?

在项目开发和运行过程中,遇到内存不足导致的OOM(Out of Memory)问题是比较常见的情况。OOM问题可能出现在以下一些场景中:

大数据量处理:当项目需要处理大量的数据时,如读取大型文件、处理大型数据库结果集等,如果没有适当的内存管理策略,会导致内存占用过高,最终耗尽可用内存。 内存泄漏:如果代码中存在内存泄漏的问题,即分配的内存没有被正确释放,随着程序的执行,内存占用不断增加,最终耗尽可用内存。 并发访问:在并发场景下,多个线程或协程同时访问和操作共享的内存区域,如果没有适当的同步机制和资源管理,可能会出现内存竞争和内存溢出问题。 解决OOM问题的方法可以有多种:

优化内存使用:通过分析项目中的内存使用情况,优化算法、数据结构或业务逻辑,减少内存占用。可以使用内存分析工具(如Go的pprof包)来识别内存使用较高的部分,并进行针对性的优化。 增加可用内存:如果项目中遇到的OOM问题是因为数据量过大,可以考虑增加可用内存的方式来解决,如增加服务器的内存配置或使用分布式缓存等。 限制资源使用:在并发场景下,可以通过限制并发访问的数量或采用合适的调度算法来控制资源的使用,避免过度占用内存。 检测和修复内存泄漏:通过内存泄漏检测工具或代码审查等方式,找出代码中存在的内存泄漏问题,并进行修复。 合理设置GC参数:对于使用垃圾回收机制的语言,可以根据项目的特点和需求,调整垃圾回收的参数,如内存阈值、垃圾回收周期等,以更好地管理和释放内存。 总之,解决OOM问题需要对项目的内存使用情况进行分析和优化,同时采取适当的措施来增加可用内存、修复内存泄漏、限制资源使用等,以确保项目的稳定运行和良好的性能。

项目中使用go遇到的坑?

谈一下Go的GC机制

说下三色标记算法的原理

go的mutx怎么使用,乐观和悲观锁分别怎么实现,使用场景是什么?