面试题答案
一键面试原理
在这种场景下,读操作可以并发执行,因为读操作不会修改数据,不会产生数据竞争。而写操作会改变数据,所以需要在写操作时加锁,防止其他协程在写操作进行时读取或写入数据,保证数据一致性。对于读操作,可以使用读锁(RWMutex
中的读锁),允许多个读操作同时进行;写操作使用写锁,保证写操作的原子性,同一时间只有一个写操作能执行。
示例代码
package main
import (
"fmt"
"sync"
)
var (
data int
rwmu sync.RWMutex
wg sync.WaitGroup
)
func read(id int) {
defer wg.Done()
rwmu.RLock()
defer rwmu.RUnlock()
fmt.Printf("Reader %d reads data: %d\n", id, data)
}
func write(id int) {
defer wg.Done()
rwmu.Lock()
defer rwmu.Unlock()
data++
fmt.Printf("Writer %d writes data: %d\n", id, data)
}
func main() {
for i := 0; i < 3; i++ {
wg.Add(1)
go read(i)
}
for i := 0; i < 1; i++ {
wg.Add(1)
go write(i)
}
wg.Wait()
}
在上述代码中:
sync.RWMutex
用于读写锁。read
函数使用rwmu.RLock()
获取读锁,允许多个读操作同时进行,完成后使用rwmu.RUnlock()
释放读锁。write
函数使用rwmu.Lock()
获取写锁,保证同一时间只有一个写操作能执行,完成后使用rwmu.Unlock()
释放写锁。- 在
main
函数中启动多个读协程和一个写协程,通过sync.WaitGroup
等待所有协程完成。