shad-go/rwmutex/README.md

60 lines
3.3 KiB
Markdown
Raw Permalink Normal View History

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
Для выполнения этих свойств достаточно двух каналов.
#### Активное ожидание
Ваше решение не должно использовать активное ожидание. Активное ожидание (busy wait)
это ситуация, когда заблокированная горутина проверяет условие в вечном цикле. Например:
```go
func (wg *WaitGroup) Wait() {
for {
wg.lock <- struct{}{}
if wg.ch1 == 0 {
<-wg.lock
return
}
<-wg.lock
}
}
```