面试题答案
一键面试互斥锁(Mutex)应用场景
互斥锁主要用于保护共享资源,确保同一时间只有一个 goroutine 能够访问该资源,防止数据竞争。适用于读写操作都可能修改共享资源状态的场景。
示例业务场景:银行账户转账操作。多个 goroutine 可能同时进行转账操作,需要保证账户余额在修改时的一致性。
package main
import (
"fmt"
"sync"
)
type BankAccount struct {
balance int
mutex sync.Mutex
}
func (b *BankAccount) Transfer(amount int) {
b.mutex.Lock()
defer b.mutex.Unlock()
b.balance += amount
}
func main() {
account := BankAccount{balance: 100}
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
account.Transfer(10)
}()
}
wg.Wait()
fmt.Println("Final balance:", account.balance)
}
读写锁(RWMutex)应用场景
读写锁适用于读操作远多于写操作的场景。它允许多个 goroutine 同时进行读操作,但写操作时会独占资源,阻止其他读写操作。
示例业务场景:缓存数据读取。大量 goroutine 频繁读取缓存数据,偶尔有 goroutine 更新缓存数据。
package main
import (
"fmt"
"sync"
)
type Cache struct {
data map[string]interface{}
rwmu sync.RWMutex
}
func (c *Cache) Read(key string) interface{} {
c.rwmu.RLock()
defer c.rwmu.RUnlock()
return c.data[key]
}
func (c *Cache) Write(key string, value interface{}) {
c.rwmu.Lock()
defer c.rwmu.Unlock()
if c.data == nil {
c.data = make(map[string]interface{})
}
c.data[key] = value
}
func main() {
cache := Cache{}
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
cache.Write(fmt.Sprintf("key%d", id), id)
}(i)
}
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
result := cache.Read(fmt.Sprintf("key%d", id%5))
fmt.Printf("goroutine %d read: %v\n", id, result)
}(i)
}
wg.Wait()
}