sync.RWMutex
выполняет как предпочтительную запись, так и предпочитаемую запись. Все зависит от того, как вы используете его для получения предпочтительной записи или чтения.
Берет википедию код ссылки псевда как пример блокировки-For-Read (в ситуации чтения предпочтительного):
* Input: mutex m, condition variable c, integer r (number of readers waiting), flag w (writer waiting).
* Lock m (blocking).
* While w:
* wait c, m[a]
* Increment r.
* Unlock m.
и шаблон блокировка для-записи в sistuation чтения предпочтительного в качестве пока вы по образцу выше для блокировки-For-Читает:
* Lock m (blocking).
* While (w or r > 0):
* wait c, m
* Set w to true.
* Unlock m.
вы можете увидеть этот механизм в игре в течение как RWMutex
реализуется. Помните, что рамки Go просто Go код - просмотреть код, чтобы увидеть, как это реализовано:
https://golang.org/src/sync/rwmutex.go?s=879:905#L20
29 // RLock locks rw for reading.
30 func (rw *RWMutex) RLock() {
31 if race.Enabled {
32 _ = rw.w.state
33 race.Disable()
34 }
35 if atomic.AddInt32(&rw.readerCount, 1) < 0 {
36 // A writer is pending, wait for it.
37 runtime_Semacquire(&rw.readerSem)
38 }
39 if race.Enabled {
40 race.Enable()
41 race.Acquire(unsafe.Pointer(&rw.readerSem))
42 }
43 }
Ключ отметить, в приведенном выше коде, который дает вам ваш integer r
в rw.readerSem
википедия пример картины, какие языки (например, Go и другие) называют Семафор:
http://www.golangpatterns.info/concurrency/semaphores
реальное мясо от ожидания на линии 37, для runtime_Semaquire()
:
https://golang.org/src/sync/runtime.go
11 // Semacquire waits until *s > 0 and then atomically decrements it.
12 // It is intended as a simple sleep primitive for use by the synchronization
13 // library and should not be used directly.
14 func runtime_Semacquire(s *uint32)
Зная это, и видя, как Приращивает RWMutex.RLock()
чтения, что число, вы можете реорганизовывать свой код соответственно.
Взгляните на то, как RWMutex.RUnlock
декрементах что, но самое главное, как RWMutex.Lock()
заставляет ждать всех активных читателей:
71 // Lock locks rw for writing.
72 // If the lock is already locked for reading or writing,
73 // Lock blocks until the lock is available.
74 // To ensure that the lock eventually becomes available,
75 // a blocked Lock call excludes new readers from acquiring
76 // the lock.
77 func (rw *RWMutex) Lock() {
78 if race.Enabled {
79 _ = rw.w.state
80 race.Disable()
81 }
82 // First, resolve competition with other writers.
83 rw.w.Lock()
84 // Announce to readers there is a pending writer.
85 r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
86 // Wait for active readers.
87 if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
88 runtime_Semacquire(&rw.writerSem)
89 }
90 if race.Enabled {
91 race.Enable()
92 race.Acquire(unsafe.Pointer(&rw.readerSem))
93 race.Acquire(unsafe.Pointer(&rw.writerSem))
94 }
95 }
Это, скорее всего, почему вы видите 2-го чтения ожидания.
Помните, что семафоры делятся не только с созданным вами экземпляром RWMutex
, но и на протяжении всего времени выполнения, чтобы спланировать другие горуты и другие блокировки. Следовательно, почему попытка заставить шаблон может принести больше вреда, чем пользы в целом в приложении.
Моя рекомендация - сделать шаг назад и рассмотреть, почему вы предпочитаете блокировку в вашей архитектуре вообще. Действительно ли вы на уровне производительности, что переключение контекста процессора замедляет ваше высокочастотное приложение?Я бы сказал, что есть более систематический подход, который можно было бы предпринять, вместо того, чтобы пытаться реализовать шаблон «блокировки чтения с привилегией» только потому, что он звучит круто и звучит так, будто он решает все ваши проблемы. Каковы ваши контрольные показатели? Каков размер входных данных и сколько параллельных процессов? Нужно ли делиться этим? Является ли это потреблением памяти в ХБ ГБ и вы можете переключиться на то, чтобы помещать вещи в стек (например, каналы, без блокировки мьютекса)? Как насчет прочитанных данных в стеке и сохранить набор записи для блокировки? Как долго до тех пор, пока GC не очистит стек, а не будет держать вещи в куче? Etc и т.д.
Ницца. Я не использую мьютекс много и просто дал длинный разлив на том, как его можно исследовать. – eduncan911