Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //go:build !solution
- package rwmutex
- import "sync/atomic"
- // A RWMutex is a reader/writer mutual exclusion lock.
- // The lock can be held by an arbitrary number of readers or a single writer.
- // The zero value for a RWMutex is an unlocked mutex.
- //
- // If a goroutine holds a RWMutex for reading and another goroutine might
- // call Lock, no goroutine should expect to be able to acquire a read lock
- // until the initial read lock is released. In particular, this prohibits
- // recursive read locking. This is to ensure that the lock eventually becomes
- // available; a blocked Lock call excludes new readers from acquiring the
- // lock.
- type RWMutex struct {
- readerSem chan struct{}
- writerSem chan struct{}
- readerCount atomic.Int32
- }
- // New creates *RWMutex.
- func New() *RWMutex {
- rSem := make(chan struct{}, 1)
- wrSem := make(chan struct{}, 1)
- return &RWMutex{rSem, wrSem, atomic.Int32{}}
- }
- // RLock locks rw for reading.
- //
- // It should not be used for recursive read locking; a blocked Lock
- // call excludes new readers from acquiring the lock. See the
- // documentation on the RWMutex type.
- func (rw *RWMutex) RLock() { // мы по сути под мьютексом это делаем
- rw.writerSem <- struct{}{} // error
- rw.readerCount.Add(1)
- select { // обозначили, что есть читатели
- case rw.readerSem <- struct{}{}:
- default:
- }
- <-rw.writerSem
- }
- // RUnlock undoes a single RLock call;
- // it does not affect other simultaneous readers.
- // It is a run-time error if rw is not locked for reading
- // on entry to RUnlock.
- func (rw *RWMutex) RUnlock() {
- select {
- case rw.writerSem <- struct{}{}: // Если RLock владеет, то он быстро отдаст; если Lock, то долго стоим
- if readersRemain := rw.readerCount.Add(-1); readersRemain == 0 {
- <-rw.readerSem
- }
- <-rw.writerSem
- default:
- if readersRemain := rw.readerCount.Add(-1); readersRemain == 0 {
- <-rw.readerSem
- }
- }
- }
- // Lock locks rw for writing.
- // If the lock is already locked for reading or writing,
- // Lock blocks until the lock is available.
- func (rw *RWMutex) Lock() {
- rw.writerSem <- struct{}{}
- rw.readerSem <- struct{}{}
- <-rw.readerSem
- }
- // Unlock unlocks rw for writing. It is a run-time error if rw is
- // not locked for writing on entry to Unlock.
- //
- // As with Mutexes, a locked RWMutex is not associated with a particular
- // goroutine. One goroutine may RLock (Lock) a RWMutex and then
- // arrange for another goroutine to RUnlock (Unlock) it.
- func (rw *RWMutex) Unlock() {
- <-rw.writerSem
- }
- // TODO: 2 ридера сделали RLock, далее врайтер сделал Lock, после этого если придёт ридер, то он исполнится после врайтера
- // Когда в очереди есть писатель, то читатели блочатся
- // В RUnlock мы иногда могли выпихнуть <-rw.writersSem, когда там ждал писатель
- // 1) RLock
- // 2) Lock
- // 3) 100 x RLock
- // 4) RUnlock
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement