推荐答案
在 Go 语言中,sync.RWMutex 是一个读写锁,允许多个读操作同时进行,但写操作是独占的。以下是使用 sync.RWMutex 实现读写锁的示例代码:
// www.javascriptcn.com code example
package main
import (
"fmt"
"sync"
"time"
)
var (
counter int
rwMutex sync.RWMutex
)
func main() {
// 启动多个读协程
for i := 0; i < 5; i++ {
go readCounter(i)
}
// 启动一个写协程
go writeCounter()
// 等待协程执行完毕
time.Sleep(2 * time.Second)
}
func readCounter(id int) {
rwMutex.RLock() // 读锁
defer rwMutex.RUnlock()
fmt.Printf("Reader %d: counter = %d\n", id, counter)
}
func writeCounter() {
rwMutex.Lock() // 写锁
defer rwMutex.Unlock()
counter++
fmt.Printf("Writer: counter = %d\n", counter)
}本题详细解读
1. sync.RWMutex 的基本概念
sync.RWMutex 是 Go 语言标准库中提供的一种读写锁。它允许多个读操作同时进行,但写操作是独占的。这意味着:
- 当一个协程持有读锁时,其他协程可以继续获取读锁,但不能获取写锁。
- 当一个协程持有写锁时,其他协程既不能获取读锁,也不能获取写锁。
2. 读写锁的使用方法
读锁(RLock 和 RUnlock):用于保护读操作。多个协程可以同时持有读锁。
rwMutex.RLock():获取读锁。rwMutex.RUnlock():释放读锁。
写锁(Lock 和 Unlock):用于保护写操作。写锁是独占的,同一时间只能有一个协程持有写锁。
rwMutex.Lock():获取写锁。rwMutex.Unlock():释放写锁。
3. 示例代码解析
读操作:在
readCounter函数中,使用rwMutex.RLock()获取读锁,读取counter的值,然后使用rwMutex.RUnlock()释放读锁。多个读协程可以同时执行读操作。写操作:在
writeCounter函数中,使用rwMutex.Lock()获取写锁,修改counter的值,然后使用rwMutex.Unlock()释放写锁。写操作是独占的,同一时间只能有一个写协程执行。
4. 注意事项
- 死锁:在使用
sync.RWMutex时,要确保在获取锁后及时释放锁,否则可能会导致死锁。 - 性能:读写锁适用于读多写少的场景,可以显著提高并发性能。但在写操作频繁的场景中,读写锁的性能可能不如普通的互斥锁。
通过合理使用 sync.RWMutex,可以在保证数据一致性的同时,提高并发读操作的性能。