Go uses ordinary locks to implement read-write locks

Rough and simple, the idea is to use a mutex as a resource lock, use two integers to record the number of readers and writers, and use an internal lock to protect the two integers and mutex. Read and write operations are mutually exclusive, write and write operations are mutually exclusive, read Read operations are not mutually exclusive.

type RWMutex struct {
    
    
	mu  sync.Mutex  // 锁定资源的锁
	lock   sync.Mutex  // 保护读者数和写者数的锁
	reader int
	writer int
}

func (rwm *RWMutex) RLock() {
    
    
	// 在写锁已被锁定的情况下试图锁定读锁,会阻塞当前的goroutine
WAIT:
	for rwm.writer > 0 {
    
    
		time.Sleep(time.Millisecond * 1)
	}

	rwm.lock.Lock()
	// double check
	if rwm.writer > 0 {
    
    
		rwm.lock.Unlock()
		goto WAIT
	}
	// 在读锁已被锁定的情况下再试图锁定读锁,并不会阻塞当前的 goroutine
	if rwm.reader > 0 {
    
    
		rwm.reader++
		rwm.lock.Unlock()
		return
	}

	rwm.reader++
	rwm.mu.Lock()
	rwm.lock.Unlock()
}

func (rwm *RWMutex) RUnlock() {
    
    
	rwm.lock.Lock()
	if rwm.reader > 1 {
    
    
		rwm.reader--
		rwm.lock.Unlock()
		return
	}

	rwm.reader--
	rwm.mu.Unlock()
	rwm.lock.Unlock()
}

func (rwm *RWMutex) WLock() {
    
    
	// 在写锁已被锁定的情况下再试图锁定写锁,会阻塞当前的 goroutine。
	// 在读锁已被锁定的情况下试图锁定写锁,同样会阻塞当前的 goroutine。
	WAIT:
	for rwm.reader > 0 || rwm.writer > 0 {
    
    
		time.Sleep(time.Millisecond * 1)
	}
	rwm.lock.Lock()
	// double check
	if rwm.reader > 0 || rwm.writer > 0{
    
    
		rwm.lock.Unlock()
		goto WAIT
	}
	rwm.writer++
	rwm.mu.Lock()
	rwm.lock.Unlock()
}

func (rwm *RWMutex) WUnlock() {
    
    
	rwm.lock.Lock()
	rwm.writer--
	rwm.mu.Unlock()
	rwm.lock.Unlock()
}

Guess you like

Origin blog.csdn.net/qq_35753140/article/details/104848166