Golang实现简易读写锁(带注释,可运行)

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:实现写优先逻辑

猜你喜欢

转载自blog.csdn.net/weixin_45440484/article/details/140918928