面试题答案
一键面试设计思路
- 互斥锁(Mutex):为共享资源加锁,确保同一时间只有一个goroutine能访问共享资源,从而保证资源的安全访问。
- 读写锁(RWMutex):如果读操作远多于写操作,可以使用读写锁。多个goroutine可以同时进行读操作,但写操作时会独占资源,防止其他读或写操作。
- defer与锁的配合:在函数开始时加锁,使用defer在函数结束时解锁,确保锁能正确释放,即使函数中出现异常。
- 错误处理:在资源操作过程中,对可能出现的错误进行及时处理,避免错误传播导致资源泄漏或程序崩溃。
关键代码片段
package main
import (
"fmt"
"sync"
)
// 定义共享资源
type SharedResource struct {
data int
mu sync.Mutex
}
// 写操作
func (sr *SharedResource) writeData(newData int, wg *sync.WaitGroup) {
defer wg.Done()
sr.mu.Lock()
defer sr.mu.Unlock()
// 模拟可能出现的错误操作
if newData < 0 {
fmt.Println("错误:数据不能为负数")
return
}
sr.data = newData
fmt.Printf("写入数据: %d\n", sr.data)
}
// 读操作
func (sr *SharedResource) readData(wg *sync.WaitGroup) {
defer wg.Done()
sr.mu.RLock()
defer sr.mu.RUnlock()
fmt.Printf("读取数据: %d\n", sr.data)
}
func main() {
var wg sync.WaitGroup
sharedResource := SharedResource{}
// 模拟多个写操作
for i := 0; i < 3; i++ {
wg.Add(1)
go sharedResource.writeData(i, &wg)
}
// 模拟多个读操作
for i := 0; i < 3; i++ {
wg.Add(1)
go sharedResource.readData(&wg)
}
wg.Wait()
}
在上述代码中:
SharedResource
结构体包含一个共享数据data
和一个互斥锁mu
。writeData
方法使用mu.Lock()
和defer mu.Unlock()
来确保写操作的线程安全,并处理了可能的错误情况。readData
方法使用mu.RLock()
和defer mu.RUnlock()
来确保读操作的线程安全。- 在
main
函数中,通过sync.WaitGroup
来等待所有goroutine完成,模拟了高并发场景下的资源访问。