面试题答案
一键面试Mutex锁适用场景
Mutex(互斥锁)适用于读写操作都可能修改共享资源的场景,确保同一时间只有一个 goroutine 能够访问共享资源,以防止数据竞争。 例如,在一个银行账户转账的场景中,需要修改账户余额,这是一个既涉及读(获取当前余额)又涉及写(更新余额)的操作,就可以使用Mutex锁。
package main
import (
"fmt"
"sync"
)
type BankAccount struct {
balance int
mutex sync.Mutex
}
func (a *BankAccount) Withdraw(amount int) {
a.mutex.Lock()
defer a.mutex.Unlock()
if a.balance >= amount {
a.balance -= amount
}
}
func main() {
account := BankAccount{balance: 1000}
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
account.Withdraw(100)
}()
}
wg.Wait()
fmt.Println("Final balance:", account.balance)
}
RWMutex锁适用场景
RWMutex(读写互斥锁)适用于读操作远多于写操作的场景。它允许多个 goroutine 同时进行读操作,但只允许一个 goroutine 进行写操作。当有写操作时,所有读操作和其他写操作都会被阻塞。 例如,在一个缓存系统中,数据读取频率高,而更新频率低。
package main
import (
"fmt"
"sync"
)
type Cache struct {
data map[string]string
rwmu sync.RWMutex
}
func (c *Cache) Get(key string) string {
c.rwmu.RLock()
defer c.rwmu.RUnlock()
return c.data[key]
}
func (c *Cache) Set(key, value string) {
c.rwmu.Lock()
defer c.rwmu.Unlock()
if c.data == nil {
c.data = make(map[string]string)
}
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()
key := fmt.Sprintf("key-%d", id)
cache.Set(key, fmt.Sprintf("value-%d", id))
}(i)
}
wg.Wait()
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
key := fmt.Sprintf("key-%d", id)
value := cache.Get(key)
fmt.Printf("Key: %s, Value: %s\n", key, value)
}(i)
}
wg.Wait()
}