мьютексы

This commit is contained in:
badkaktus 2019-10-08 17:09:19 +03:00
parent f627d67e1a
commit be57797702
3 changed files with 31 additions and 30 deletions

View File

@ -35,7 +35,7 @@ Select
WaitGroups WaitGroups
Ограничение скорости (Rate Limiting) Ограничение скорости (Rate Limiting)
Атомарные счетчики (Atomic Counters) Атомарные счетчики (Atomic Counters)
Mutexes Мьютексы (Mutexes)
Stateful Goroutines Stateful Goroutines
Sorting Sorting
Sorting by Functions Sorting by Functions

View File

@ -1,7 +1,7 @@
// In the previous example we saw how to manage simple // В предыдущем примере мы увидели, как управлять простым
// counter state using [atomic operations](atomic-counters). // состоянием счетчика с помощью [атомарных операций](atomic-counters).
// For more complex state we can use a <em>[mutex](http://en.wikipedia.org/wiki/Mutual_exclusion)</em> // Для более сложного состояния мы можем использовать <em>мьютекс(http://en.wikipedia.org/wiki/Mutual_exclusion)</em>
// to safely access data across multiple goroutines. // для безопасного доступа к данным в нескольких горутинах.
package main package main
@ -15,45 +15,45 @@ import (
func main() { func main() {
// For our example the `state` will be a map. // Для нашего примера `state` будет картой.
var state = make(map[int]int) var state = make(map[int]int)
// This `mutex` will synchronize access to `state`. // Этот `mutex` будет синхронизировать доступ к `state`.
var mutex = &sync.Mutex{} var mutex = &sync.Mutex{}
// We'll keep track of how many read and write // Мы будем отслеживать, сколько операций чтения и
// operations we do. // записи мы выполняем.
var readOps uint64 var readOps uint64
var writeOps uint64 var writeOps uint64
// Here we start 100 goroutines to execute repeated // Здесь мы запускаем 100 горутин для выполнения
// reads against the state, once per millisecond in // повторных операций чтения по состоянию, один раз
// each goroutine. // в миллисекунду в каждой горутине.
for r := 0; r < 100; r++ { for r := 0; r < 100; r++ {
go func() { go func() {
total := 0 total := 0
for { for {
// For each read we pick a key to access, // Для каждого чтения мы выбираем ключ для
// `Lock()` the `mutex` to ensure // доступа, блокируем `mutex` с помощью `Lock()` ,
// exclusive access to the `state`, read // чтобы обеспечить исключительный доступ к
// the value at the chosen key, // `состоянию`, читаем значение в выбранном ключе,
// `Unlock()` the mutex, and increment // разблокируем мьютекс `Unlock()` и увеличиваем
// the `readOps` count. // количество `readOps`.
key := rand.Intn(5) key := rand.Intn(5)
mutex.Lock() mutex.Lock()
total += state[key] total += state[key]
mutex.Unlock() mutex.Unlock()
atomic.AddUint64(&readOps, 1) atomic.AddUint64(&readOps, 1)
// Wait a bit between reads. // Немного ждем между чтениями.
time.Sleep(time.Millisecond) time.Sleep(time.Millisecond)
} }
}() }()
} }
// We'll also start 10 goroutines to simulate writes, // Запустим так же 10 горутин для симуляции записи,
// using the same pattern we did for reads. // так же как мы делали для чтения.
for w := 0; w < 10; w++ { for w := 0; w < 10; w++ {
go func() { go func() {
for { for {
@ -68,17 +68,18 @@ func main() {
}() }()
} }
// Let the 10 goroutines work on the `state` and // Пусть 10 горутин работают над `состоянием` и
// `mutex` for a second. // `мьютексом` на секунду.
time.Sleep(time.Second) time.Sleep(time.Second)
// Take and report final operation counts. // Смотрим финальное количество операций
readOpsFinal := atomic.LoadUint64(&readOps) readOpsFinal := atomic.LoadUint64(&readOps)
fmt.Println("readOps:", readOpsFinal) fmt.Println("readOps:", readOpsFinal)
writeOpsFinal := atomic.LoadUint64(&writeOps) writeOpsFinal := atomic.LoadUint64(&writeOps)
fmt.Println("writeOps:", writeOpsFinal) fmt.Println("writeOps:", writeOpsFinal)
// With a final lock of `state`, show how it ended up. // С окончательной блокировкой `состояния` смотрим,
// как все закончилось.
mutex.Lock() mutex.Lock()
fmt.Println("state:", state) fmt.Println("state:", state)
mutex.Unlock() mutex.Unlock()

View File

@ -1,10 +1,10 @@
# Running the program shows that we executed about # Запуск программы показывает, что мы выполнили около 90000
# 90,000 total operations against our `mutex`-synchronized # операций в нашем синхронизированном с `мьютексом`
# `state`. # состоянии.
$ go run mutexes.go $ go run mutexes.go
readOps: 83285 readOps: 83285
writeOps: 8320 writeOps: 8320
state: map[1:97 4:53 0:33 2:15 3:2] state: map[1:97 4:53 0:33 2:15 3:2]
# Next we'll look at implementing this same state # Далее мы рассмотрим реализацию той же задачи управления
# management task using only goroutines and channels. # состоянием с использованием только горутин и каналов.