面试题答案
一键面试读锁适用场景及原因
- 适用场景:当多个并发操作只需要读取共享资源,而不需要对其进行修改时,适合使用读锁。例如在一个Web应用中,多个用户同时请求读取配置文件信息、数据库中的只读数据等场景。
- 原因:读锁允许多个协程同时获取锁进行读取操作,因为读取操作不会改变共享资源的状态,所以多个读操作之间不会产生数据竞争问题。使用读锁可以提高并发读的效率,充分利用多核CPU的优势,提升系统性能。
写锁适用场景及原因
- 适用场景:当并发操作需要修改共享资源时,适合使用写锁。比如在银行转账操作中,需要修改账户余额;在更新数据库记录时,都需要使用写锁。
- 原因:写操作会改变共享资源的状态,如果多个写操作同时进行或者读写操作同时进行,就可能导致数据不一致的问题。写锁是独占锁,当一个协程获取了写锁,其他协程无论是读操作还是写操作都需要等待该写锁释放,这样可以保证在写操作进行时,共享资源不会被其他操作干扰,确保数据的一致性和完整性。
示例代码
package main
import (
"fmt"
"sync"
)
var (
counter int
mu sync.RWMutex
)
// 读操作
func read(wg *sync.WaitGroup) {
defer wg.Done()
mu.RLock()
fmt.Printf("Reading: %d\n", counter)
mu.RUnlock()
}
// 写操作
func write(wg *sync.WaitGroup, val int) {
defer wg.Done()
mu.Lock()
counter = val
fmt.Printf("Writing: %d\n", counter)
mu.Unlock()
}
func main() {
var wg sync.WaitGroup
// 模拟多个读操作
for i := 0; i < 3; i++ {
wg.Add(1)
go read(&wg)
}
// 模拟写操作
wg.Add(1)
go write(&wg, 42)
// 等待所有操作完成
wg.Wait()
}
在上述代码中,read
函数使用读锁进行读取操作,write
函数使用写锁进行写操作。通过这种方式,保证了在并发环境下共享资源counter
的读写安全。