面试题答案
一键面试- 方案设计
- 对于读操作频繁,写操作较少的场景,优先使用读写锁(
sync.RWMutex
)来提升读操作的并发性能。当进行写操作时,因为不允许有读操作同时进行,所以需要使用互斥锁(sync.Mutex
)来保证写操作的原子性。 - 以下是示例代码:
- 对于读操作频繁,写操作较少的场景,优先使用读写锁(
package main
import (
"fmt"
"sync"
)
type Data struct {
mu sync.Mutex
rwmu sync.RWMutex
value int
}
// Read 方法用于读操作
func (d *Data) Read() int {
d.rwmu.RLock()
defer d.rwmu.RUnlock()
return d.value
}
// Write 方法用于写操作
func (d *Data) Write(newValue int) {
d.mu.Lock()
defer d.mu.Unlock()
d.rwmu.Lock()
defer d.rwmu.Unlock()
d.value = newValue
}
- 锁的使用逻辑和切换时机
- 读操作逻辑:
- 在
Read
方法中,使用d.rwmu.RLock()
获取读锁。读锁允许多个读操作同时进行,因为读操作不会修改数据,所以多个读操作之间不会产生数据竞争。当读操作完成后,使用d.rwmu.RUnlock()
释放读锁。
- 在
- 写操作逻辑:
- 首先使用
d.mu.Lock()
获取互斥锁。这一步的目的是确保在写操作开始前,没有其他写操作正在进行。因为写操作需要保证原子性,不允许其他写操作同时修改数据。 - 然后使用
d.rwmu.Lock()
获取写锁。这一步是为了确保在写操作进行时,没有读操作同时进行。虽然读写锁本身可以在写操作时阻止读操作,但为了更严谨地保证写操作的原子性,先获取互斥锁再获取写锁。 - 当写操作完成后,先使用
d.rwmu.Unlock()
释放写锁,再使用d.mu.Unlock()
释放互斥锁。
- 首先使用
- 读操作逻辑:
通过这种方式,利用读写锁提升读操作的并发性能,同时使用互斥锁保证写操作的原子性以及写操作和读操作之间的互斥性。