MST
星途 面试题库

面试题:Go中Mutex锁与RWMutex锁适用场景的差异

请阐述在Go语言中,Mutex锁与RWMutex锁分别适用于哪些场景?并举例说明。
32.6万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

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()
}