面试题答案
一键面试资源管理分析
- 避免资源泄漏:
- 在Go语言中,对于通道(channel)这类资源,确保在不再需要时关闭它们。如果一个通道没有被关闭,并且还有协程在等待从该通道接收数据,就可能导致协程永远阻塞,造成资源泄漏。
- 使用
sync.WaitGroup
来等待所有相关的协程完成任务,避免提前退出程序而导致协程未完成清理工作。
- 避免性能瓶颈:
- 合理设置通道的缓冲区大小。如果缓冲区过小,可能导致频繁的阻塞和唤醒操作,影响性能;如果缓冲区过大,可能会浪费内存。
- 尽量减少锁的使用范围和时间。在高并发场景下,锁的竞争会成为性能瓶颈。对于共享资源的访问,应尽量采用无锁的数据结构或减少共享资源的使用。
优化代码示例
package main
import (
"fmt"
"sync"
)
// Barrier 结构体用于并发任务协调
type Barrier struct {
n int
count int
mutex sync.Mutex
cond *sync.Cond
}
// NewBarrier 创建一个新的Barrier实例
func NewBarrier(n int) *Barrier {
b := &Barrier{
n: n,
count: 0,
}
b.cond = sync.NewCond(&b.mutex)
return b
}
// Wait 等待所有协程到达Barrier
func (b *Barrier) Wait() {
b.mutex.Lock()
b.count++
if b.count == b.n {
b.cond.Broadcast()
} else {
for b.count < b.n {
b.cond.Wait()
}
}
b.mutex.Unlock()
}
func main() {
var wg sync.WaitGroup
numWorkers := 5
barrier := NewBarrier(numWorkers)
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("Worker %d started\n", id)
barrier.Wait()
fmt.Printf("Worker %d passed the barrier\n", id)
}(i)
}
wg.Wait()
}
在这个示例中:
Barrier
结构体使用sync.Mutex
和sync.Cond
来协调并发任务,避免了使用通道可能带来的一些复杂的资源管理问题。sync.Cond
基于sync.Mutex
,在需要广播或等待时进行高效的同步操作,减少了锁的竞争,从而避免性能瓶颈。sync.WaitGroup
用于确保所有协程完成任务后程序才退出,避免资源泄漏。