2021-03-05 11:58:41 +00:00
|
|
|
|
## rwmutex
|
|
|
|
|
|
|
|
|
|
[sync.RWMutex](https://golang.org/pkg/sync/#RWMutex) -- это примитив синхронизации,
|
2022-03-06 02:06:00 +00:00
|
|
|
|
предоставляющий доступ к критической секции произвольному количеству читателей и
|
2021-03-05 13:32:52 +00:00
|
|
|
|
не более, чем одному писателю. При этом, если есть писатель, то читателей нет.
|
2021-03-05 11:58:41 +00:00
|
|
|
|
|
|
|
|
|
### Что нужно сделать?
|
|
|
|
|
|
2022-03-06 02:06:00 +00:00
|
|
|
|
Нужно написать реализацию RWMutex, используя каналы.
|
2021-03-05 11:58:41 +00:00
|
|
|
|
|
|
|
|
|
Использование пакета [sync](https://golang.org/pkg/sync) в этой задаче запрещено!
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
type RWMutex struct {}
|
|
|
|
|
|
|
|
|
|
func (rw *RWMutex) Lock() {}
|
|
|
|
|
func (rw *RWMutex) Unlock() {}
|
|
|
|
|
|
|
|
|
|
func (rw *RWMutex) RLock() {}
|
|
|
|
|
func (rw *RWMutex) RUnlock() {}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`RWMutex` можно представлять себе как две блокировки, блокировка на чтение и блокировка на запись.
|
|
|
|
|
|
|
|
|
|
`New()` возвращает `RWMutex`, в котором ни одна из блокировок не взята.
|
|
|
|
|
|
|
|
|
|
Процессы, желающие изменить данные (писатели), берут блокировку на запись с помощью метода `Lock`.
|
|
|
|
|
Процессы, желающие прочитать данные (читатели), берут блокировку на чтение с помощью метода `RLock`.
|
|
|
|
|
По окончании записи писатель отпускает блокировку на запись (`Unlock`).
|
2021-03-08 12:29:15 +00:00
|
|
|
|
С блокировкой на чтение связано число активных читателей.
|
2021-03-05 11:58:41 +00:00
|
|
|
|
При взятии блокировки (`RLock`) это число инкрементируется.
|
|
|
|
|
При завершении чтения (`RUnlock`) блокировка на чтение уменьшает счётчик.
|
|
|
|
|
|
|
|
|
|
#### Свойства
|
|
|
|
|
1. Писатель не заблокируется при взятии блокировки только при условии,
|
|
|
|
|
что никакой другой писатель и никакой другой читатель не владеет соответствующей блокировкой.
|
|
|
|
|
2. Если какой-то писатель взял блокировку на запись, любой новый писатель или читатель заблокируется при взятии блокировки.
|
|
|
|
|
3. Если какой-то читатель взял блокировку на чтение, любой новый писатель заблокируется на взятии блокировки.
|
2021-03-10 08:14:21 +00:00
|
|
|
|
Однако любой другой читатель сможет взять блокировку на чтение.
|
2021-03-05 11:58:41 +00:00
|
|
|
|
|
|
|
|
|
Для выполнения этих свойств достаточно двух каналов.
|
2024-06-05 17:36:34 +00:00
|
|
|
|
|
|
|
|
|
#### Активное ожидание
|
|
|
|
|
|
|
|
|
|
Ваше решение не должно использовать активное ожидание. Активное ожидание (busy wait)
|
|
|
|
|
это ситуация, когда заблокированная горутина проверяет условие в вечном цикле. Например:
|
|
|
|
|
|
|
|
|
|
```go
|
|
|
|
|
func (wg *WaitGroup) Wait() {
|
|
|
|
|
for {
|
|
|
|
|
wg.lock <- struct{}{}
|
|
|
|
|
if wg.ch1 == 0 {
|
|
|
|
|
<-wg.lock
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
<-wg.lock
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|