@@ -31,6 +31,9 @@ type RWMutex struct {
3131
3232const rwMutexMaxReaders = 1 << 30
3333
34+ // Lock locks rw for writing.
35+ // If the lock is already locked for reading or writing,
36+ // Lock blocks until the lock is available.
3437func (rw * RWMutex ) Lock () {
3538 // Exclusive lock for writers.
3639 rw .writerLock .Lock ()
@@ -56,6 +59,12 @@ func (rw *RWMutex) Lock() {
5659 rw .writer .Store (0 )
5760}
5861
62+ // Unlock unlocks rw for writing. It is a run-time error if rw is
63+ // not locked for writing on entry to Unlock.
64+ //
65+ // As with Mutexes, a locked [RWMutex] is not associated with a particular
66+ // goroutine. One goroutine may [RWMutex.RLock] ([RWMutex.Lock]) a RWMutex and then
67+ // arrange for another goroutine to [RWMutex.RUnlock] ([RWMutex.Unlock]) it.
5968func (rw * RWMutex ) Unlock () {
6069 // Signal that new readers can lock this mutex.
6170 waiting := rw .readers .Add (rwMutexMaxReaders )
@@ -68,6 +77,31 @@ func (rw *RWMutex) Unlock() {
6877 rw .writerLock .Unlock ()
6978}
7079
80+ // TryLock tries to lock m and reports whether it succeeded.
81+ //
82+ // Note that while correct uses of TryLock do exist, they are rare,
83+ // and use of TryLock is often a sign of a deeper problem
84+ // in a particular use of mutexes.
85+ func (rw * RWMutex ) TryLock () bool {
86+ // Check for active writers
87+ if ! rw .writerLock .TryLock () {
88+ return false
89+ }
90+ // Have write lock, now check for active readers
91+ n := uint32 (rwMutexMaxReaders )
92+ if ! rw .readers .CompareAndSwap (0 , - n ) {
93+ // Active readers, give up write lock
94+ rw .writerLock .Unlock ()
95+ return false
96+ }
97+ return true
98+ }
99+
100+ // RLock locks rw for reading.
101+ //
102+ // It should not be used for recursive read locking; a blocked Lock
103+ // call excludes new readers from acquiring the lock. See the
104+ // documentation on the [RWMutex] type.
71105func (rw * RWMutex ) RLock () {
72106 // Add us as a reader.
73107 newVal := rw .readers .Add (1 )
@@ -79,6 +113,10 @@ func (rw *RWMutex) RLock() {
79113 }
80114}
81115
116+ // RUnlock undoes a single [RWMutex.RLock] call;
117+ // it does not affect other simultaneous readers.
118+ // It is a run-time error if rw is not locked for reading
119+ // on entry to RUnlock.
82120func (rw * RWMutex ) RUnlock () {
83121 // Remove us as a reader.
84122 one := uint32 (1 )
@@ -98,6 +136,25 @@ func (rw *RWMutex) RUnlock() {
98136 }
99137}
100138
139+ // TryRLock tries to lock rw for reading and reports whether it succeeded.
140+ //
141+ // Note that while correct uses of TryRLock do exist, they are rare,
142+ // and use of TryRLock is often a sign of a deeper problem
143+ // in a particular use of mutexes.
144+ func (rw * RWMutex ) TryRLock () bool {
145+ for {
146+ c := rw .readers .Load ()
147+ if c < 0 {
148+ // There is a writer waiting or writing.
149+ return false
150+ }
151+ if rw .readers .CompareAndSwap (c , c + 1 ) {
152+ // Read lock obtained.
153+ return true
154+ }
155+ }
156+ }
157+
101158type Locker interface {
102159 Lock ()
103160 Unlock ()
0 commit comments