1、简单读写锁实现,未实现写优先逻辑。
(1)代码:
package main
import (
"fmt"
"sync"
"time"
)
type RWLock struct {
readCount int
writeCount int
mutex sync.Mutex // 一个互斥锁,用于保护共享变量的读写操作。
readCond sync.Cond // 一个条件变量,用于协调读操作和写操作。
writeCond sync.Cond
}
// 给条件变量 (readCond 和 writeCond) 设置它们的关联互斥锁
func (rw *RWLock) Init() {
rw.readCond.L = &rw.mutex
// 调用 readCond.Wait() 时,它会自动释放 rw.mutex,并在条件满足时重新获取它。
rw.writeCond.L = &rw.mutex
}
// RLock方法中,首先获取锁,然后判断是否有写操作正在进行,如果有,则调用条件变量的Wait方法等待,直到写计数器为0。然后将读计数器加1,并释放锁。
func (rw *RWLock) RLock() {
rw.mutex.Lock()
for rw.writeCount > 0 {
rw.readCond.Wait() // 将当前 goroutine 置于等待状态,并在收到通知后重新尝试获取锁。自动释放 rw.mutex,并在条件满足时重新获取它。
}
rw.readCount++
rw.mutex.Unlock()
}
// RUnlock方法中,获取锁,将读计数器减1,如果读计数器为0,则唤醒写操作的等待者,并释放锁。
func (rw *RWLock) RUnlock() {
rw.mutex.Lock()
rw.readCount--
if rw.readCount == 0 {
rw.writeCond.Signal() // 调用了Signal()或Broadcast()方法来唤醒。
}
rw.mutex.Unlock()
}
// WLock方法中,首先获取锁,然后判断是否有其他读操作或写操作正在进行,如果有,则调用条件变量的Wait方法等待,
// 直到读计数器和写计数器都为0。然后将写计数器加1,并释放锁。
func (rw *RWLock) WLock() {
rw.mutex.Lock()
for rw.readCount > 0 || rw.writeCount > 0 {
rw.writeCond.Wait()
}
rw.writeCount++
rw.mutex.Unlock()
}
// 获取锁,将写计数器减1,然后分别唤醒读操作和写操作的等待者,并释放锁。
func (rw *RWLock) WUnlock() {
rw.mutex.Lock()
rw.writeCount--
rw.readCond.Signal()
rw.writeCond.Signal()
rw.mutex.Unlock()
}
func main() {
var rwLock RWLock
rwLock.Init()
var wg sync.WaitGroup
numReaders := 4
numWriters := 3
// 创建写者 goroutine
for i := 0; i < numWriters; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("Writer %d is trying to write\n", id)
rwLock.WLock()
fmt.Printf("Writer %d is writing\n", id)
time.Sleep(2 * time.Second) // 模拟写入操作的时间
rwLock.WUnlock()
fmt.Printf("Writer %d finished writing\n", id)
}(i)
}
// 创建读者 goroutine
for i := 0; i < numReaders; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("Reader %d is trying to read\n", id)
rwLock.RLock()
fmt.Printf("Reader %d is reading\n", id)
time.Sleep(time.Second) // 模拟读取操作的时间
rwLock.RUnlock()
fmt.Printf("Reader %d finished reading\n", id)
}(i)
}
wg.Wait()
fmt.Println("All readers and writers have finished")
}
(2)运行结果:
(3)To do:实现写优先逻辑