мьютексы
This commit is contained in:
parent
f627d67e1a
commit
be57797702
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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.
|
# состоянием с использованием только горутин и каналов.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user