OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package sync | 5 package sync |
6 | 6 |
7 // An RWMutex is a reader/writer mutual exclusion lock. | 7 // An RWMutex is a reader/writer mutual exclusion lock. |
8 // The lock can be held by an arbitrary number of readers | 8 // The lock can be held by an arbitrary number of readers |
9 // or a single writer. | 9 // or a single writer. |
10 // RWMutexes can be created as part of other | 10 // RWMutexes can be created as part of other |
11 // structures; the zero value for a RWMutex is | 11 // structures; the zero value for a RWMutex is |
12 // an unlocked mutex. | 12 // an unlocked mutex. |
13 // | 13 // |
14 // Writers take priority over Readers: no new RLocks | 14 // Writers take priority over Readers: no new RLocks |
15 // are granted while a blocked Lock call is waiting. | 15 // are granted while a blocked Lock call is waiting. |
16 type RWMutex struct { | 16 type RWMutex struct { |
17 » w» » Mutex;» // held if there are pending readers or writers | 17 » w Mutex // held if there are pending readers or writers |
18 » r» » Mutex;» // held if the w is being rd | 18 » r Mutex // held if the w is being rd |
19 » readerCount» uint32;»// number of pending readers | 19 » readerCount uint32 // number of pending readers |
20 } | 20 } |
21 | 21 |
22 // RLock locks rw for reading. | 22 // RLock locks rw for reading. |
23 // If the lock is already locked for writing or there is a writer already waitin
g | 23 // If the lock is already locked for writing or there is a writer already waitin
g |
24 // to r the lock, RLock blocks until the writer has released the lock. | 24 // to r the lock, RLock blocks until the writer has released the lock. |
25 func (rw *RWMutex) RLock() { | 25 func (rw *RWMutex) RLock() { |
26 // Use rw.r.Lock() to block granting the RLock if a goroutine | 26 // Use rw.r.Lock() to block granting the RLock if a goroutine |
27 // is waiting for its Lock. This is the prevent starvation of W in | 27 // is waiting for its Lock. This is the prevent starvation of W in |
28 // this situation: | 28 // this situation: |
29 // A: rw.RLock() // granted | 29 // A: rw.RLock() // granted |
30 // W: rw.Lock() // waiting for rw.w().Lock() | 30 // W: rw.Lock() // waiting for rw.w().Lock() |
31 // B: rw.RLock() // granted | 31 // B: rw.RLock() // granted |
32 // C: rw.RLock() // granted | 32 // C: rw.RLock() // granted |
33 // B: rw.RUnlock() | 33 // B: rw.RUnlock() |
34 // ... (new readers come and go indefinitely, W is starving) | 34 // ... (new readers come and go indefinitely, W is starving) |
35 » rw.r.Lock(); | 35 » rw.r.Lock() |
36 if xadd(&rw.readerCount, 1) == 1 { | 36 if xadd(&rw.readerCount, 1) == 1 { |
37 // The first reader locks rw.w, so writers will be blocked | 37 // The first reader locks rw.w, so writers will be blocked |
38 // while the readers have the RLock. | 38 // while the readers have the RLock. |
39 rw.w.Lock() | 39 rw.w.Lock() |
40 } | 40 } |
41 » rw.r.Unlock(); | 41 » rw.r.Unlock() |
42 } | 42 } |
43 | 43 |
44 // RUnlock undoes a single RLock call; | 44 // RUnlock undoes a single RLock call; |
45 // it does not affect other simultaneous readers. | 45 // it does not affect other simultaneous readers. |
46 // It is a run-time error if rw is not locked for reading | 46 // It is a run-time error if rw is not locked for reading |
47 // on entry to RUnlock. | 47 // on entry to RUnlock. |
48 func (rw *RWMutex) RUnlock() { | 48 func (rw *RWMutex) RUnlock() { |
49 if xadd(&rw.readerCount, -1) == 0 { | 49 if xadd(&rw.readerCount, -1) == 0 { |
50 // last reader finished, enable writers | 50 // last reader finished, enable writers |
51 rw.w.Unlock() | 51 rw.w.Unlock() |
52 } | 52 } |
53 } | 53 } |
54 | 54 |
55 // Lock locks rw for writing. | 55 // Lock locks rw for writing. |
56 // If the lock is already locked for reading or writing, | 56 // If the lock is already locked for reading or writing, |
57 // Lock blocks until the lock is available. | 57 // Lock blocks until the lock is available. |
58 // To ensure that the lock eventually becomes available, | 58 // To ensure that the lock eventually becomes available, |
59 // a blocked Lock call excludes new readers from acquiring | 59 // a blocked Lock call excludes new readers from acquiring |
60 // the lock. | 60 // the lock. |
61 func (rw *RWMutex) Lock() { | 61 func (rw *RWMutex) Lock() { |
62 » rw.r.Lock(); | 62 » rw.r.Lock() |
63 » rw.w.Lock(); | 63 » rw.w.Lock() |
64 » rw.r.Unlock(); | 64 » rw.r.Unlock() |
65 } | 65 } |
66 | 66 |
67 // Unlock unlocks rw for writing. | 67 // Unlock unlocks rw for writing. |
68 // It is a run-time error if rw is not locked for writing | 68 // It is a run-time error if rw is not locked for writing |
69 // on entry to Unlock. | 69 // on entry to Unlock. |
70 // | 70 // |
71 // Like for Mutexes, | 71 // Like for Mutexes, |
72 // a locked RWMutex is not associated with a particular goroutine. | 72 // a locked RWMutex is not associated with a particular goroutine. |
73 // It is allowed for one goroutine to RLock (Lock) an RWMutex and then | 73 // It is allowed for one goroutine to RLock (Lock) an RWMutex and then |
74 // arrange for another goroutine to RUnlock (Unlock) it. | 74 // arrange for another goroutine to RUnlock (Unlock) it. |
75 func (rw *RWMutex) Unlock()» { rw.w.Unlock() } | 75 func (rw *RWMutex) Unlock() { rw.w.Unlock() } |
OLD | NEW |